从C#调用非托管(C ++)函数时的PInvoke错误 [英] PInvoke error when calling unmanaged (C++) function from C#

查看:195
本文介绍了从C#调用非托管(C ++)函数时的PInvoke错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个我没有编写和测试的非法的C ++ DLL。未构图的代码在未构造的控制台应用程序中构建并运行时,会很好。函数声明如下所示。

  #ifndef IMPORT_MYLIB 
#define MYLIB_API __declspec(dllexport)
# else
#define MYLIB_API __declspec(dllimport)
#endif

命名空间gsod_data_parsing {
externC
{
MYLIB_API int parse_raw_gsod_file_nocb
const char * path,
int temp_threshold
);
}
}

我正在尝试从托管应用程序调用它。我在C#文件中声明这个功能:

  [DllImport(GSODDLL.dll)] 
public static extern int parse_raw_gsod_file_nocb(
[MarshalAs(UnmanagedType.LPStr)] string path,
int temp_threshold
);

然后,这些函数在几个并行任务中执行,如下所示:

  //启动任务 - 这在后台线程运行... 
task1 = Task.Factory.StartNew(()=>
{
int t1 = parse_raw_gsod_file_nocb(filePaths [i],this._frostTemp);
return(t1 == 0);
},this._tokenSource.Token);

它似乎运行正常,但是然后(我相信函数执行完毕)我得到以下错误。


调用PInvoke函数'Database
Creator!Database_Creator.Form1 :: parse_raw_gsod_file_nocb'有
不平衡堆栈。这可能是因为托管的PInvoke
签名与非托管目标签名不匹配。检查
调用约定,PInvoke签名的参数匹配
目标非管理签名。


我看到类似的问题 here 但我不太明白接受的答案。



任何人都有任何想法?
谢谢

解决方案

所以原来我的问题是由于调用约定不匹配。根据这个文档,默认通话C / C ++程序的Windows中的约定是Cdecl。另外,根据这个文档 PInvoke的默认调用约定是StdCall。我原来没有指定任何调用约定,因此它默认为StdCall。由于这些约定规定了函数调用后堆栈的清理方式,所以在函数执行结束时抛出了错误。



更改我的PInvoke声明修正了我的问题:

  [DllImport(GSODDLL.dll,CallingConvention = CallingConvention.Cdecl)] 
public static extern int parse_raw_gsod_file_nocb(
[MarshalAs(UnmanagedType.LPStr)] string path,
int temp_threshold
);


I have an unmanged C++ dll that I have written and tested. The unmanged code woks fine when built and run in an unmanged console app. The function declaration is shown below.

#ifndef IMPORT_MYLIB
#    define MYLIB_API __declspec(dllexport)
#else
#    define MYLIB_API __declspec(dllimport)
#endif

namespace gsod_data_parsing {
extern "C"
{
  MYLIB_API int parse_raw_gsod_file_nocb(
    const char *path,
    int temp_threshold
  );
}
}

I am trying to call this from a managed application. I declare the function in my C# file like this:

 [DllImport("GSODDLL.dll")]
 public static extern int parse_raw_gsod_file_nocb(
   [MarshalAs(UnmanagedType.LPStr)] string path,
   int temp_threshold
 );

These functions are then being executed on a couple parallel tasks like shown below:

// Start a task - this runs on the background thread...
task1 = Task.Factory.StartNew(() => 
{
  int t1 = parse_raw_gsod_file_nocb(filePaths[i], this._frostTemp);
  return (t1 == 0);
}, this._tokenSource.Token);

It appears to run fine at first but then (I believe when the function has finished executing) I get the following error.

A call to PInvoke function 'Database Creator!Database_Creator.Form1::parse_raw_gsod_file_nocb' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

I saw a similar question here but I don't quite understand the accepted answer.

Anyone have any ideas? Thanks

解决方案

So it turns out my problem was due to calling convention mismatch. According to this document the default calling convention in windows for C/C++ programs is Cdecl. Also, according to this document the default calling convention for PInvoke is StdCall. I originally did not specify any calling convention so it was defaulting to StdCall. Since these conventions specify how the stack is cleaned up after the function call, it makes sense that the error was being thrown at the end of the function's execution.

Changing my PInvoke declaration to this fixed my problem:

[DllImport("GSODDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int parse_raw_gsod_file_nocb(
  [MarshalAs(UnmanagedType.LPStr)] string path,
  int temp_threshold
);

这篇关于从C#调用非托管(C ++)函数时的PInvoke错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆