参见指针指向的函数签名

本文关键字:函数 指针 | 更新日期: 2023-09-27 18:04:14

我正在调用非托管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)。可能是因为我需要传递更多的参数。我不知道那个方法的签名。我怎样才能找到方法的签名?指针不为空,所以我知道函数存在。如果我输入的方法名不正确,我得到一个空指针。一种解决方案是输入不同的签名,直到它不会崩溃。可能有很多组合。所以简而言之,我知道指针指向一个函数。我怎么知道这个函数的特征?

参见指针指向的函数签名

您需要查看SDK附带的头文件。需要注意的一件事是呼叫惯例。您可能需要将[UnmanagedFunctionPointer(CallingConvention.Cdecl)]添加到您的委托减速中,在需要时不这样做将导致此确切错误(将获得错误的参数)。

您的第二个呼叫有一个错别字:

Delegate2 x = (Delegate2)Marshal.GetDelegateForFunctionPointer(ptr, typeof(Delegate1));                              

传递的是Delegate1的类型,然后强制转换为Delegate2。