如何从 C# 代码将 *& 和 **& 参数传递给 C++ dll
How to pass *& and **& parameter to C++ dll from C# code
我有如下标准的 C++ dll
函数原型和结构定义
extern "C" int __declspec(dllexport) DoOPeration(DataStruct *&, DataStructInfo **&);
typedef struct
{
int count;
float CountData;
bool flg;
BYTE* data;
char info[100];
}DataStruct;
typedef struct
{
int count;
bool flg;
BYTE* data;
}DataStructInfo;
DoOPeration函数的实现如下
int __declspec(dllexport) ImageAnalyze(DataStruct *&all, DataStructInfo **&part)
{
int ret = 0;
try
{
if(all->count == 0)
return(ERR_PARAMERROR);
for(cnt = 0 ; cnt < all->count ; cnt++)
{
if(part[cnt]->data== NULL)
return(ERR_NO_IMAGE);
}
}
catch(int err)
{
return(err);
}
catch(...)
{
return(-2);
}
return(ret);
}
对应于上面我添加了 C# 边代码作为下面的标准
DLL导入、结构(class)定义
[DllImport(@"C:\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DoOperation(ref DataStruct all, ref DataStructInfo[] part);
[StructLayout(LayoutKind.Sequential)]
public class DataStruct
{
int count = 0;
float CountData = 0;
bool flg = 0;
byte[] data = null;
string info = 0;
}
[StructLayout(LayoutKind.Sequential)]
public class DataStructInfo
{
int count = 0;
bool flg = 0;
byte[] data;
}
// DoOperation function calling
DataStruct alls = new DataStruct(); // set all required parameter
DataStructInfo[] part= new DataStructInfo[3]; // set all required parameter
int ret = DoOperation(ref alls, ref part);
从c#代码调用C++ dll函数后,我观察了c++ dll中函数参数的值。
- 参数[所有]值都正确传递
- 参数 [part] 值未正确传递(显示一些垃圾值)
请告诉我有关传递第二个参数的信息,即来自 c# 代码的 (**&)。
另外,如果我还有其他错误,请告诉我,以便我改正。
注意:我无法更改C++ dll代码
我通过以下方法得到了解决方案。
C# 端代码
DLL导入,结构定义
[DllImport(@"C:\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DoOperation(ref IntPtr all, ref IntPtr[] part);
[StructLayout(LayoutKind.Sequential)]
public struct DataStruct
{
public int count { get; set; }
public float CountData { get; set; }
public bool flg { get; set; }
public IntPtr data { get; set; }
public string info { get; set; }
}
[StructLayout(LayoutKind.Sequential)]
public struct DataStructInfo
{
public int count { get; set; }
public bool flg { get; set; }
public IntPtr data { get; set; }
}
// First parameter
DataStruct alls = new DataStruct(); // set all required parameter
IntPtr intPtrsAll = new IntPtr();
intPtrsAll = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(DataStruct)));
Marshal.StructureToPtr<DataStruct>(alls, intPtrsAll, false);
// Second parameter
DataStructInfo[] part= new DataStructInfo[3]; // set all required parameter
IntPtr[] intPtrsParts= new IntPtr[part.Length];
for (int i = 0; i < intPtrsParts.Length; i++)
{
intPtrsParts[i] = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(DataStructInfo)));
Marshal.StructureToPtr<DataStructInfo>(part[i], intPtrsParts[i], false);
}
int ret = DoOperation(ref intPtrsAll, ref intPtrsParts);
注意:为了在 C# 端设置 byte[] 数据,我使用了 [IntPtr] 和下面的方法
byte[] rowData = GetRawBytes(dataHandler); // function to read byte[] data
int size = Marshal.SizeOf(rowData[0]) * rowData.Length;
data = Marshal.AllocHGlobal(size); // IntPtr property of struct's
Marshal.Copy(rowData, 0, data, rowData.Length);
我有如下标准的 C++ dll
函数原型和结构定义
extern "C" int __declspec(dllexport) DoOPeration(DataStruct *&, DataStructInfo **&);
typedef struct
{
int count;
float CountData;
bool flg;
BYTE* data;
char info[100];
}DataStruct;
typedef struct
{
int count;
bool flg;
BYTE* data;
}DataStructInfo;
DoOPeration函数的实现如下
int __declspec(dllexport) ImageAnalyze(DataStruct *&all, DataStructInfo **&part)
{
int ret = 0;
try
{
if(all->count == 0)
return(ERR_PARAMERROR);
for(cnt = 0 ; cnt < all->count ; cnt++)
{
if(part[cnt]->data== NULL)
return(ERR_NO_IMAGE);
}
}
catch(int err)
{
return(err);
}
catch(...)
{
return(-2);
}
return(ret);
}
对应于上面我添加了 C# 边代码作为下面的标准
DLL导入、结构(class)定义
[DllImport(@"C:\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DoOperation(ref DataStruct all, ref DataStructInfo[] part);
[StructLayout(LayoutKind.Sequential)]
public class DataStruct
{
int count = 0;
float CountData = 0;
bool flg = 0;
byte[] data = null;
string info = 0;
}
[StructLayout(LayoutKind.Sequential)]
public class DataStructInfo
{
int count = 0;
bool flg = 0;
byte[] data;
}
// DoOperation function calling
DataStruct alls = new DataStruct(); // set all required parameter
DataStructInfo[] part= new DataStructInfo[3]; // set all required parameter
int ret = DoOperation(ref alls, ref part);
从c#代码调用C++ dll函数后,我观察了c++ dll中函数参数的值。
- 参数[所有]值都正确传递
- 参数 [part] 值未正确传递(显示一些垃圾值)
请告诉我有关传递第二个参数的信息,即来自 c# 代码的 (**&)。
另外,如果我还有其他错误,请告诉我,以便我改正。
注意:我无法更改C++ dll代码
我通过以下方法得到了解决方案。
C# 端代码
DLL导入,结构定义
[DllImport(@"C:\TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int DoOperation(ref IntPtr all, ref IntPtr[] part);
[StructLayout(LayoutKind.Sequential)]
public struct DataStruct
{
public int count { get; set; }
public float CountData { get; set; }
public bool flg { get; set; }
public IntPtr data { get; set; }
public string info { get; set; }
}
[StructLayout(LayoutKind.Sequential)]
public struct DataStructInfo
{
public int count { get; set; }
public bool flg { get; set; }
public IntPtr data { get; set; }
}
// First parameter
DataStruct alls = new DataStruct(); // set all required parameter
IntPtr intPtrsAll = new IntPtr();
intPtrsAll = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(DataStruct)));
Marshal.StructureToPtr<DataStruct>(alls, intPtrsAll, false);
// Second parameter
DataStructInfo[] part= new DataStructInfo[3]; // set all required parameter
IntPtr[] intPtrsParts= new IntPtr[part.Length];
for (int i = 0; i < intPtrsParts.Length; i++)
{
intPtrsParts[i] = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(DataStructInfo)));
Marshal.StructureToPtr<DataStructInfo>(part[i], intPtrsParts[i], false);
}
int ret = DoOperation(ref intPtrsAll, ref intPtrsParts);
注意:为了在 C# 端设置 byte[] 数据,我使用了 [IntPtr] 和下面的方法
byte[] rowData = GetRawBytes(dataHandler); // function to read byte[] data
int size = Marshal.SizeOf(rowData[0]) * rowData.Length;
data = Marshal.AllocHGlobal(size); // IntPtr property of struct's
Marshal.Copy(rowData, 0, data, rowData.Length);