【问题标题】:Calling Unmanaged Code from Managed Code从托管代码调用非托管代码
【发布时间】:2013-08-24 20:13:30
【问题描述】:

有人知道我如何解决这个错误吗?

错误:

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

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

步骤是

  1. 找到包含这些函数的 .dll。
  2. 将 .dll 加载到内存中
  3. 在内存中定位函数的地址
  4. 将此对象的内存表示转换为数据格式(编组)

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")] 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);`

由于名称修改,我在 GetProcAddress 方法的函数名称参数中使用了“_Connect@32”而不是“Connect”。

当我调试时,我在包含语句的行收到此错误

长校验 = connect(1, 0, 12, 9600, 0, 0, 8, 0);

【问题讨论】:

    标签: c# ipc


    【解决方案1】:

    C/C++ long 在 Windows 中是 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)] 
    

    对于 Windows API 的DllImport,您应该使用

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

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

    【讨论】:

      【解决方案2】:

      您使用 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,通常)

      【讨论】:

        猜你喜欢
        • 2010-09-18
        • 1970-01-01
        • 2015-02-24
        • 1970-01-01
        • 2013-12-29
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        相关资源
        最近更新 更多