首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从托管代码调用非托管代码

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

Stack Overflow用户
提问于 2013-08-22 07:55:16
回答 2查看 2.1K关注 0票数 1

有人知道我是怎么纠正这个错误的吗?

错误:

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

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

步骤如下

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

DLL有一个带有声明的函数。

代码语言:javascript
复制
long    __stdcall Connect (long,long,long,long,long,long,long,long);`

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

代码语言:javascript
复制
[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")公共静态extern IntPtr LoadLibrary(string dllToLoad);

代码语言:javascript
复制
    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);


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

现在,当我试图使用这个函数时,就会出现错误。

代码语言:javascript
复制
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方法的函数名参数中使用了“GetProcAddress”而不是"Connect“。

在调试时,我在包含语句的行处得到此错误。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-22 07:58:27

C/C++ long在Windows中是32位,所以在.net中是一个int。尝试改变它(在Unix上,它更像一个IntPtr)

代码语言:javascript
复制
[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

代码语言:javascript
复制
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 

对于Windows的DllImport,您应该使用

代码语言:javascript
复制
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]

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

票数 2
EN

Stack Overflow用户

发布于 2013-08-22 08:03:39

您使用LoadLibrary()而不是直接使用PInvoking有什么原因吗?

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

代码语言:javascript
复制
[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,通常是这样)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18374667

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档