含传递String数组和整数数组为C一结构++ DLL [英] Passing a Structure containing an array of String and an array of Integer into a C++ DLL
问题描述
,这里的code:
在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 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?
推荐答案
GCHandle.Alloc
的 分配指定的对象的,其中的一个普通手柄创建一个句柄管理对象.. 。其中$ p $被收集pvents管理对象的
什么你要找的是 System.Runtime.InteropServices.Marshal
的方法,它允许你做的事情一样复制管理对象由非托管$访问的存储器C $℃。不幸的是,根据这,指针在你的结构使其成为一个有点难度比很多其他的事情元帅(在这个意义上,许多其他的事情可以使用相应的P为自动编组/ Invoke的属性),但它仍然是可能的。我已经试过了这一点,它的工作原理:
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:
APP_PARAM param = new APP_PARAM();
string[] text = new string[] { "A", "B", "C" };
param.numData = text.Length;
// Manually allocate an array of pointers, one for each string. arr holds the array's address.
IntPtr arr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * text.Length);
try
{
param.text = arr;
IntPtr[] unmanagedText = new IntPtr[text.Length];
try
{
// Create a null-terminated ANSI string in unmanaged memory for each element in text.
for (int i = 0; i < text.Length; i++)
unmanagedText[i] = Marshal.StringToHGlobalAnsi(text[i]);
// Copy the addresses of the unmanaged strings into the manually allocated array.
// I don't know of any way to make an unmanaged copy of a managed array in one call.
Marshal.Copy(unmanagedText, 0, arr, unmanagedText.Length);
// param now looks like what the C++ code is expecting (except for the array of int).
StartApp(param);
}
finally
{
foreach (IntPtr str in unmanagedText)
Marshal.FreeHGlobal(str);
}
}
finally
{
Marshal.FreeHGlobal(arr);
}
你必须有类似的分配/释放code你的int类型数组,有自己的try / finally块,以确保FreeHGlobal被调用。
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.
这篇关于含传递String数组和整数数组为C一结构++ DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!