我正在调用一个非托管的dll。我这样做的方式就像:
// Kernel functions used to load dll
#region Kernell 32
[DllImport("kernel32")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
#endregion
public void Test()
{
IntPtr dllHandle = LoadLibrary(@"C:\Program Files (x86)\SEGGER\JLinkARM_SDK_V484c\JLinkARM.dll");
// here is a function that enables me to read data from a chip
var ptr = GetProcAddress(loadedDllHandle, @"JLINK_HSS_Read");
{
Delegate1 readMem = (Delegate1)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));
// then if I want to read an integer from memory address 0x100 I will do
byte[] dataToRead = new byte[4];
unsafe
{
fixed (byte* fixedPointer = dataToRead)
{
// <----- FIRST CALL TO DLL WORKS GREAT!!!!!!!!!!!!!!!!
var retn = readMem(0x100, 4, (IntPtr)fixedPointer);
}
}
}
// there is another function called JLINK_HSS_Start
ptr = GetProcAddress(loadedDllHandle, @"JLINK_HSS_Start");
{
Delegate2 x = (Delegate2)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));
unsafe
{
var m = x(5); // here I get an exception!
}
}
}
我得到的例外:
附加信息:调用PInvoke函数 'JLINK!Jlink.HighSpeedSampling.Hss + JLINK_HSS_Start_Handler ::调用' 堆栈不平衡。这可能是因为托管PInvoke 签名与非托管目标签名不匹配。检查一下 调用约定和PInvoke签名匹配的参数 目标非托管签名。
第一个函数调用有效,第二个函数调用
换句话说,我不能叫x(5)。可能是因为我需要传递更多参数。我不知道该方法的签名。我怎样才能找到该方法的签名。指针不为null,所以我知道函数存在。如果我错误地键入方法名称,我会得到一个空指针。一种解决方案是键入不同的签名,直到它不崩溃。可能有这么多组合。 所以总之我知道指针指向一个函数。我怎么知道该功能的签名?
答案 0 :(得分:1)
您需要查看SDK附带的头文件。值得注意的是调用约定。您可能需要将[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
添加到代理减速中,而在需要时不会这样做会导致此确切错误(因为这会导致参数错误)。
答案 1 :(得分:0)
第二次通话中有拼写错误:
Delegate2 x = (Delegate2)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));
您传递的是Delegate1类型,然后转换为Delegate2。