在.net外部组件中使用c++本地dll抛出异常
Using C++ native dll in .Net External component has thrown an exception
我试图在c#中使用本机c++ dll,并且正在获得"外部组件抛出异常",错误代码为-2147467259。
c#:[DllImport(@"MyDLL.dll", CharSet = CharSet.Auto)]
public static extern string MyFunction([MarshalAs(UnmanagedType.LPStr)] StringBuilder input);
c++: __declspec(dllexport) char * __stdcall MyFunction(const char* inputPtr);
该函数在c++中工作得很好。我怎样才能找到这个错误?我已经尝试使用字符串和字符串生成器的参数。
我找到了这篇文章http://tom-shelton.net/index.php/2008/12/11/creating-a-managed-wrapper-for-a-lib-file/
它详细说明了使用托管c++在c++中包装非托管静态库的方法,该库可以在托管语言中使用。这是解决这个问题的好方法吗?lib可以是一个非托管的dll吗?
试试http://blog.rednael.com/2008/08/29/MarshallingUsingNativeDLLsInNET.aspx上的技巧-这已经节省了好几次了:-)
如果参数是in-only(而不是out),则不需要stringbuilder。如果它是一个输出参数(或ref),你应该使用stringbuilder并使用stringbuilder构造函数预分配缓冲区。
我可以猜测问题是,你正在返回一个Ansi字符串,而不是预期的unicode字符串。这会导致默认的pinvoke封送处理程序读取太多内存。
试试这个:[DllImport(@"MyDLL.dll", CharSet = CharSet. auto)][return: MarshalAs(UnmanagedType.LPStr)]public static extern string MyFunction([MarshalAs(UnmanagedType.LPStr)] string input);
在任何情况下,在绝大多数情况下,编写Ansi c++代码没有任何意义。我建议将c++代码仅转换为unicode(不是char,而是wchar_t)。
CharSet = CharSet. auto ??使用的字符集。Ansi
你不能使用字符数组作为返回值,c++分配的内存块不能被c#使用!在您的情况下,您可能需要将其复制到c#托管内存中。使用StringBuilder或MarshalAs属性,它将为您将缓冲区复制到c#托管内存中。
你必须改变你的c++函数,你的c++函数必须写入目标缓冲区,这个缓冲区必须被分配,所以它至少包含你需要的字符数加1(对于null终止字符)。
[DllImport(@"MyDLL.dll", CharSet = CharSet.Ansi)]
private static extern void MyFunction([MarshalAs(UnmanagedType.LPStr)] string input, StringBuilder result);
public static string MyFunctionPublic(string input)
{
StringBuilder sb = new StringBuilder(input.Length + 1);
MyFunction(input, sb);
return sb.ToString();
}
我希望你的C函数做这样的事情:
void __stdcall MyFunction(const char* input, char* result)
{
strcpy(result, input); // this is a dummy stupid code to show how it works.
}
可能你需要一个函数来告诉你在c#中需要分配多少字节。这个函数可以是这样的:
int __stdcall ComputeMyFunctionBytes(const char* input)
{
return strlen(input); // this is a dummy stupid code to show how it works.
}
永远不要将一块已分配的内存返回给c#,它不能做任何事情,也不能取消分配,也不能读写,直到你使用不安全的代码,但这不是你想要做的。
一篇好文章似乎在这里:http://www.devx.com/dotnet/Article/6990/1954
还要注意c#使用unicode,每个字符16位,因此它将从ansi转换为unicode。
- 将地址分配给本地指针后,公共对象的变量将消失
- 如何在本地机器上运行c++和javascript客户端代码(hackerbank风格)
- 编写代码时C++出现错误:错误 1 错误 C2601:'circle':本地函数定义是非法的
- 如何使用 Boost Asio 在 Android 上获取我的本地 udp IP 地址?
- 在成员dynamic_bitset上使用 boost::from_block_range 时出错,但在本地dynamic
- 在本地网络中通过OpenCV(C++)实时流式传输图像
- C++:在被本地字符串捕获后释放或销毁 malloc'd char *?
- C++:处理线程本地对象销毁
- 如何强制 Thrift 仅接受来自本地主机的连接
- 将对象创建为全局/静态对象会崩溃,而本地对象不会崩溃
- 具有捕获引用的长寿命(非本地)λ
- 如果原型是本地的,则使用流 I/O C++类型约束将失败
- C++ 未初始化的本地(非全局)int 数组中的元素类型到底是什么?
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 如何制作带有本地声明头的链表?
- 如何初始化大线程本地对象?
- CMake 导入本地共享库以及如何将其包含在标头中
- 我是否需要在 c++ 中从本地指针中释放分配的内存?
- 使用 sftp_open() 使用 C++ 中的 SFTP libssh 将文件从本地复制到远程时,File 返回 N
- 使用 c 或 c++ 运行本地服务器的最佳方法