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;
}