将包含 String 数组和 Integer 数组的结构传递到 C++ DLL
我在将 VB.NET 编组到 C++ 时遇到问题,代码如下:
在 C++ DLL 中:
struct APP_PARAM
{
int numData;
LPCSTR *text;
int *values;
};
int App::StartApp(APP_PARAM params)
{
for (int i = 0; i < numLines; i++)
{
OutputDebugString(params.text[i]);
}
}
在 VB.NET 中:
<StructLayoutAttribute(LayoutKind.Sequential)> _
Public Structure APP_PARAM
Public numData As Integer
Public text As System.IntPtr
Public values As System.IntPtr
End Structure
Declare Function StartApp Lib "AppSupport.dll" (ByVal params As APP_PARAM) As Integer
Sub Main()
Dim params As APP_PARAM
params.numData = 3
Dim text As String() = {"A", "B", "C"}
Dim textHandle As GCHandle = GCHandle.Alloc(text)
params.text = GCHandle.ToIntPtr(textHandle)
Dim values As Integer() = {10, 20, 30}
Dim valuesHandle As GCHandle = GCHandle.Alloc(values)
params.values = GCHandle.ToIntPtr(heightHandle)
StartApp(params)
textHandle.Free()
valuesHandle.Free()
End Sub
我检查了 C++ 端,OutputDebugString 的输出是垃圾,文本数组包含随机字符。这样做的正确方法是什么?
I'm having problems with marshaling in VB.NET to C++, here's the code :
In the C++ DLL :
struct APP_PARAM
{
int numData;
LPCSTR *text;
int *values;
};
int App::StartApp(APP_PARAM params)
{
for (int i = 0; i < numLines; i++)
{
OutputDebugString(params.text[i]);
}
}
In VB.NET :
<StructLayoutAttribute(LayoutKind.Sequential)> _
Public Structure APP_PARAM
Public numData As Integer
Public text As System.IntPtr
Public values As System.IntPtr
End Structure
Declare Function StartApp Lib "AppSupport.dll" (ByVal params As APP_PARAM) As Integer
Sub Main()
Dim params As APP_PARAM
params.numData = 3
Dim text As String() = {"A", "B", "C"}
Dim textHandle As GCHandle = GCHandle.Alloc(text)
params.text = GCHandle.ToIntPtr(textHandle)
Dim values As Integer() = {10, 20, 30}
Dim valuesHandle As GCHandle = GCHandle.Alloc(values)
params.values = GCHandle.ToIntPtr(heightHandle)
StartApp(params)
textHandle.Free()
valuesHandle.Free()
End Sub
I checked the C++ side, the output from the OutputDebugString is garbage, the text array contains random characters. What is the correct way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
GCHandle.Alloc
"分配普通句柄对于指定的对象”,“创建托管对象的句柄...这可以防止托管对象被收集”。您正在寻找的是 System.Runtime.InteropServices.Marshal 中的方法,这些方法允许您执行诸如将托管对象复制到非托管代码可访问的内存之类的操作。不幸的是,根据 this,指针在你的结构中,它比许多其他东西更难封送(从某种意义上说,许多其他东西可以使用适当的 P/Invoke 属性自动封送),但这仍然是可能的。我已经尝试过这个方法并且它有效:
您必须为 int 值数组拥有类似的分配/释放代码,并具有自己的 try/finally 块以确保调用 FreeHGlobal。
GCHandle.Alloc
"Allocates a Normal handle for the specified object", which "creates a handle to a managed object ... which prevents the managed object from being collected".What you're looking for is the methods from
System.Runtime.InteropServices.Marshal
, which allow you to do things like copy managed objects to memory accessible by unmanaged code. Unfortunately, according to this, the pointers in your struct make it a little harder to marshal than many other things (in the sense that many other things can be automatically marshalled using the appropriate P/Invoke attributes), but it's still possible. I've tried this out and it works:You'll have to have similar allocation/free code for your array of int values, with its own try/finally blocks to make sure FreeHGlobal is called.
您需要使用
Marshal
类中的方法之一。You need to use one of the methods from the
Marshal
class.