从托管代码调用非托管代码

时间:2013-08-22 07:55:17

标签: c# ipc

任何人都知道我如何修复此错误?

ERROR:

  

对PInvoke函数的调用使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

我正在使用P / Invoke从托管代码调用本机代码。通过动态链接库导入本机代码。

步骤

  1. 找到包含这些功能的.dll。
  2. 将.dll加载到内存
  3. 在内存中找到功能的地址
  4. 将对象的内存表示转换为数据格式(编组)
  5. DLL具有声明

    的功能
    long    __stdcall Connect (long,long,long,long,long,long,long,long);`
    

    在我的应用程序中,我创建了一个委托

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate long delConnect(long a, long b, long c, long d, long e, long f, long g, long h);`
    

    然后我创建了一个用于加载dll和在内存中定位函数地址的类

    `静态类NativeMethods     {         [的DllImport(" KERNEL32.DLL&#34)]         public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
    
    
        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }`
    

    现在,当我尝试使用该功能时,我收到错误

    IntPtr pDll = NativeMethods.LoadLibrary("serial.dll");
    IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "_Connect@32");
    delConnect connect = (delConnect)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(delConnect)); 
    long check = connect(1, 0, 12, 9600, 0, 0, 8, 0);
    bool result = NativeMethods.FreeLibrary(pDll);`
    

    我用过" _Connect @ 32"而不是" Connect"在GetProcAddress方法的函数名参数中,因为名称重整。

    当我调试时,我在包含语句

    的行中收到此错误
      

    long check = connect(1,0,12,9600,0,0,8,0);

2 个答案:

答案 0 :(得分:2)

Windows中的C / C ++ long为32位,int中为.net。尝试更改它(在Unix上它更像是IntPtr

[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
private delegate int delConnect(int a, int b, int c, int d, int e, int f, int g, int h);

也许代替StdCall尝试Cdecl

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 

对于DllImport Windows API,您应该使用

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]

因此,如果可能,.NET使用Unicode变体,而不是Ansi变体。

答案 1 :(得分:0)

您是否有理由使用LoadLibrary()而不是直接使用PInvoking?

如果您尝试这样做会发生什么:

[DllImport("serial.dll", EntryPoint = "_Connect@32", CallingConvention = CallingConvention.StdCall)]
static extern int DelConnect(int a, int b, int c, int d, int e, int f, int g, int h);

(注意C#int == C ++ long,通常)