C# DLL에서 함수 동적 호출
9421 단어 C#
[System.Runtime.InteropServices.DllImport("E:\\Project\\DLL\\XXX.dll", EntryPoint = "OpenComm", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] public static extern int OpenComm(int port);
E:\\Project\\DLL\\XX.dll, 이 경로 테스트는 변수로 대체할 수 없다. 즉, 반드시 이렇게 써야 한다. 그러면 매번 사이트가 경로를 바꿀 때마다 여기서 한 번 바꿔야 한다. 나는 이런 상황을 만났고 방법은 사용할 수 있다.
메서드2: DLL에서 C# 함수를 동적으로 호출
참조:http://www.cnblogs.com/kingmoon/archive/2011/04/26/2028833.html
namespace DllOperation
{
#region
//public static int Open()
// {
// int DID = 0;
// Dynamicloadingdll ddl = new Dynamicloadingdll();
// String DllPath = "E:\\Project\\ElectricitySellingSystem\\ElectricitySellings\\DLL\\HCard32.dll";
// ddl.LoadDll(DllPath);
// ddl.LoadFun("UC_OpenComm");
// object[] Parameters = new object[] { (int)100 }; // 100
// Type[] ParameterTypes = new Type[] { typeof(int) }; // int
// DllOperation.Dynamicloadingdll.ModePass[] themode = new DllOperation.Dynamicloadingdll.ModePass[] { DllOperation.Dynamicloadingdll.ModePass.ByValue }; //
// Type Type_Return = typeof(int); // int
// object DeviceID= ddl.Invoke(Parameters, ParameterTypes, themode,Type_Return).ToString();
// DID = int.Parse(DeviceID.ToString());
// Parameters = new object[] { DID }; // 0
// ddl.LoadFun("UC_CloseComm");
// ddl.Invoke(Parameters, ParameterTypes, themode, Type_Return).ToString();
// ddl.UnLoadDll();
// return DID;
// }
#endregion
///
/// Dynamicloadingdll
///
public class Dynamicloadingdll
{
public Dynamicloadingdll()
{
//
// TODO:
//
}
///
/// ,ByValue ,ByRef
///
public enum ModePass
{
ByValue = 0x0001,
ByRef = 0x0002
}
#region LoadLibrary、GetProcAddress、FreeLibrary hModule farProc:
///
/// :HMODULE LoadLibrary(LPCTSTR lpFileName);
///
/// DLL
///
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
///
/// : FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
///
///
///
///
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
///
/// : BOOL FreeLibrary(HMODULE hModule);
///
///
/// Dll
[DllImport("kernel32", EntryPoint = "FreeLibrary", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);
///
/// Loadlibrary
///
private IntPtr hModule = IntPtr.Zero;
///
/// GetProcAddress
///
private IntPtr farProc = IntPtr.Zero;
#endregion
#region LoadDll , , :
///
/// Dll
///
/// 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;
}
#endregion
#region LoadFun , , , :
///
///
///
///
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 + " "));
}
///
///
///
/// DLL
///
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 + " "));
}
#endregion
#region UnLoadDll Invoke ,Invoke :
///
/// Dll
///
public void UnLoadDll()
{
FreeLibrary(hModule);
hModule = IntPtr.Zero;
farProc = IntPtr.Zero;
}
//Invoke :
///
///
///
///
///
///
///
/// 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("MyFun", 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("MyFun");
return MyMethodInfo.Invoke(null, ObjArray_Parameter);// ,
}
//Invoke , :
///
///
///
///
///
///
///
///
/// 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);
}
#endregion
}
}
이렇게 하면 경로를 구성 파일에서 읽거나 Server를 통해 읽을 수 있습니다.MapPath는 물리적 경로를 가져옵니다.
C++로 작성된 Dll을 사용할 때는 직접 참조용이 아니라 중간에 전환 방법이 필요합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.