C#呼び出しC++DLL

28687 ワード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//1.           “Tzb”,     ,  “Tzb”,  “  ”-->“ ”,     “dld”,
// dynamic loading dll           。
//2.                           :
using System.Runtime.InteropServices; //   DllImport         
using System.Reflection; //    Assembly          
using System.Reflection.Emit; //    ILGenerator         

namespace WpfApplication1
{
    // “public class dld”                  :
    ///
    ///          ,ByValue       ,ByRef      
    /// 

    public enum ModePass
    {
        ByValue = 0x0001,
        ByRef = 0x0002
    }
    public class DLD
    {      

        //3.         LoadLibrary、GetProcAddress、FreeLibrary     hModule farProc:
        ///
        ///     :HMODULE LoadLibrary(LPCTSTR lpFileName);
        ///
        /// < param name="lpFileName" / >DLL    
        ///          
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        ///
        ///     : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
        ///
        /// < param name="hModule" / >                 
        /// < param name="lpProcName" / >        
        ///       

        [DllImport("kernel32.dll")]
        static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);

        ///
        ///     : BOOL FreeLibrary(HMODULE hModule);
        ///
        /// < param name="hModule" / >             
        ///           Dll

        [DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
        static extern bool FreeLibrary(IntPtr hModule);

        ///
        /// Loadlibrary            
        /// 

        private IntPtr hModule = IntPtr.Zero;

        ///
        /// GetProcAddress        
        /// 

        public IntPtr farProc = IntPtr.Zero;

        //4.         LoadDll  ,        ,       :
        ///
        ///    Dll
        ///
        /// < param name="lpFileName" / >DLL     

        public void LoadDll(string lpFileName)
        {

            hModule = LoadLibrary(lpFileName);
            if (hModule == IntPtr.Zero)
                throw (new Exception("      :" + lpFileName + "."));
        }

        //               Dll   ,    LoadDll        :
        public void LoadDll(IntPtr HMODULE)
        {
            if (HMODULE == IntPtr.Zero)
                throw (new Exception("              HMODULE    ."));
            hModule = HMODULE;
        }

        //5.         LoadFun  ,        ,        ,            :
        ///
        ///       
        ///
        /// < param name="lpProcName" / >         

        public void LoadFun(string lpProcName)
        { //

            if (hModule == IntPtr.Zero)
                throw (new Exception("            ,        LoadDll    !"));
            //       
            farProc = GetProcAddress(hModule, lpProcName);

            //
            if (farProc == IntPtr.Zero)
                throw (new Exception("      : " + lpProcName + "          "));

        }

        ///
        ///       
        ///
        /// < param name="lpFileName" / >          DLL    
        /// < param name="lpProcName" / >         

        public void LoadFun(string lpFileName, string lpProcName)
        { //           
            hModule = LoadLibrary(lpFileName);

            //
            if (hModule == IntPtr.Zero)
                throw (new Exception("      :" + lpFileName + "."));

            //       
            farProc = GetProcAddress(hModule, lpProcName);

            //
            if (farProc == IntPtr.Zero)
                throw (new Exception("      :" + lpProcName + "          "));

        }

        //6.    UnLoadDll Invoke  ,Invoke        :
        ///
        ///    Dll
        /// 

        public void UnLoadDll()
        {
            FreeLibrary(hModule);
            hModule = IntPtr.Zero;
            farProc = IntPtr.Zero;
        }

        ///
        ///         
        ///
        /// < param name="ObjArray_Parameter" / >   
        /// < param name="TypeArray_ParameterType" / >     
        /// < param name="ModePassArray_Parameter" / >       
        /// < param name="Type_Return" / >     
        ///           object

        public object Invoke(object[] ObjArray_Parameter, Type[] TypeArray_ParameterType,
                                 ModePass[] ModePassArray_Parameter, Type Type_Return)
        {

            //    3   if         ,       ,      
            if (hModule == IntPtr.Zero)
                throw (new Exception("            ,        LoadDll    !"));
            if (farProc == IntPtr.Zero)
                throw (new Exception("        ,        LoadFun    !"));
            if (ObjArray_Parameter.Length != ModePassArray_Parameter.Length)
                throw (new Exception("                  ."));

            //       MyAssemblyName        Name   
            AssemblyName MyAssemblyName = new AssemblyName();
            MyAssemblyName.Name = "InvokeFun";

            //        
            AssemblyBuilder MyAssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                                                       MyAssemblyName, AssemblyBuilderAccess.Run);
            ModuleBuilder MyModuleBuilder = MyAssemblyBuilder.DefineDynamicModule("InvokeDll");

            //          ,     “ MyFun ”,     “ Type_Return ”
            //     “ TypeArray_ParameterType ”
            MethodBuilder MyMethodBuilder = MyModuleBuilder.DefineGlobalMethod(
                                          "Init", MethodAttributes.Public | MethodAttributes.Static,
                                          Type_Return, TypeArray_ParameterType);

            //      ILGenerator ,        IL
            ILGenerator IL = MyMethodBuilder.GetILGenerator();

            int i;
            for (i = 0; i < ObjArray_Parameter.Length; i++)
            {//             
                switch (ModePassArray_Parameter[i])
                {
                    case ModePass.ByValue:
                        IL.Emit(OpCodes.Ldarg, i);
                        break;
                    case ModePass.ByRef:
                        IL.Emit(OpCodes.Ldarga, i);
                        break;
                    default:
                        throw (new Exception("   " + (i + 1).ToString() + "                ."));
                }
            }

            if (IntPtr.Size == 4)
            {//        
                IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
            }
            else if (IntPtr.Size == 8 )
            {
                IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());
            }
            else
            {
                throw new PlatformNotSupportedException();
            }

            IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, TypeArray_ParameterType);
            IL.Emit(OpCodes.Ret); //    
            MyModuleBuilder.CreateGlobalFunctions();

            //       
            MethodInfo MyMethodInfo = MyModuleBuilder.GetMethod("Init");
            return MyMethodInfo.Invoke(null, ObjArray_Parameter);//
        }

        //Invoke        ,           :
        ///
        ///         
        ///
        /// < param name="IntPtr_Function" / >     
        /// < param name="ObjArray_Parameter" / >   
        /// < param name="TypeArray_ParameterType" / >     
        /// < param name="ModePassArray_Parameter" / >       
        /// < param name="Type_Return" / >     
        ///           object

        public object Invoke(IntPtr IntPtr_Function, object[] ObjArray_Parameter,
                               Type[] TypeArray_ParameterType, ModePass[] ModePassArray_Parameter,
                               Type Type_Return)
        {

            //    2   if         ,       ,      
            if (hModule == IntPtr.Zero)
                throw (new Exception("            ,        LoadDll    !"));
            if (IntPtr_Function == IntPtr.Zero)
                throw (new Exception("      IntPtr_Function    !"));
            farProc = IntPtr_Function;
            return Invoke(ObjArray_Parameter, TypeArray_ParameterType, ModePassArray_Parameter, Type_Return);
        }            

    }
}
/*******    ******/
        private void button1_Click(object sender, RoutedEventArgs e)
        {

            DLD newDLL = new DLD();
            newDLL.LoadFun("E:\\workspaces\\WpfApplication1\\Debug\\DLL.dll", "Init");
            StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
            object[] obj = new object[] { MyStringBuilder };
            Type[] ty = new Type[] { typeof(StringBuilder) };
            ModePass[] mode = new ModePass[] { ModePass.ByValue };
            Type Type_Return = typeof(StringBuilder);
            StringBuilder j = (StringBuilder)newDLL.Invoke(obj, ty, mode, Type_Return);

        }
/********c++DLL    *******/

extern "C" __declspec(dllexport) LPTSTR Init(LPTSTR a);

LPTSTR Init(LPTSTR a)
{
    strcat((char *)a, "added");
    return a;
}