初始化 C# IntPtr 以接受来自非托管 C++ DLL 的数据?
Initializing a C# IntPtr to accept data from unmanaged C++ DLL?
我在非托管C++代码中有一个导出的函数,它需要一个指向 BStr 的指针,它将在其中写入一些文本数据(最大 258 字节)
extern "C" __declspec(dllexport)
int CppFunc(BSTR *data)
{ ... }
我希望该数据为字符串。
这行得通
[DllImport( ... CallingConvention = CallingConvention.Cdecl)]
public static extern int CppFunc([MarshalAs(UnmanagedType.BStr)] ref string data);
但它会产生内存泄漏。
我假设我应该做的是创建并传递一个 IntPtr,然后将 Bstr 封送为字符串,然后释放 IntPtr:
IntPtr p = Marshal.AllocHGlobal(512);
CppFunction(p);
string data = Marshal.PtrToStringBSTR(p);
Marshal.FreeHGlobal(p) ;
问题是,使用该代码,我在调用Marshal.PtrToStringBSTR(p)时得到一个System.AccessViolationException。
我做错了什么?!
Marshal.PtrToStringBSTR
备注的第一行是
仅对使用非托管 SysAllocString 和 SysAllocStringLen 函数分配的字符串调用此方法。
这可能就是你的崩溃的来源。
除此之外,您的C++函数期望BSTR*
(实际上是指向字符串中数据第一个字符的指针),但您向它传递指向数据的指针。
请记住,BSTR 具有特殊的结构:它以 4 个字节的长度开始,然后是数据,然后是 null。指针指向数据的第一个字符。因此,Marshal.PtrToStringBSTR
从指针向后看以查找字符串的长度 - 但这不是由Marshal.AllocHGlobal
分配的内存。
可能是您的C++函数执行类似于*data = ....AllocSysString();
的操作 - 也就是说,它永远不会读取给定的字符串,而是将指针分配给它分配的字符串。
在这种情况下,您可能需要类似以下内容:
[DllImport( ... CallingConvention = CallingConvention.Cdecl)]
public static extern int CppFunc(out IntPtr data);
...
CppFunc(out IntPtr p);
string data = Marshal.PtrToStringBSTR(p);
Marshal.FreeBSTR(p) ;
在这里,我们向它传递一个指向指针的指针。C++ 函数重新分配指针以指向 BSTR 中数据的第一个字符,我们使用它来反序列化 BSTR,然后释放它(使用知道如何释放 BSTR 的方法)。
如果不是这种情况,就不清楚为什么你的C++函数需要BSTR*
(而不是BSTR
),以及它用它做什么。我认为,在说其他事情之前,我们需要看到这一点。
如果你的C++函数取BSTR
(记住BSTR
本身就是一个指针),那么你应该做的是使用StringBuilder
(具有特定的初始容量) - 编组层将其转换为C++代码可以写入的指针,然后您可以将StringBuilder
转换为字符串。
[DllImport( ... CallingConvention = CallingConvention.Cdecl)]
public static extern int CppFunc([MarshalAs(UnmanagedType.BStr)] StringBuilder data);
...
var data = new StringBuilder(512);
CppFunction(data);
string result = data.ToString();
- 挂起和取消挂起一个文件DLL
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 导入库可以跨dll版本工作吗
- 从C++dll访问C#中的一行主要参数
- 链接到自行创建的dll失败
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何指定我希望我的LIB链接到的DLL文件?-Visual Studio 2019
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- C++:将外部库链接到dll库
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 不同的Visual Studio版本中缺少.dll
- 从DLL中删除类的实例
- 如何包装第三方DLL在R中使用
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- 系统.将数组移交给c#中动态加载的c++DLL时发生AccessViolationException
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Python ctypes:不会按预期加载 dll
- 在 C++/CLI 中将 .NET 事件从一个 DLL 引发到另一个 DLL