Return 从 c++ 函数到 c# 的结构,然后是数组 UPDATE
Return a struct from a c++ function to c# then an array UPDATE
我在 2 周内阅读了大约 100 多篇关于此的帖子,并且让自己完全困惑。这是我在 BlueSoleil 堆栈上编写的包装器。
在 C++ 中
typedef char BTINT8;
typedef unsigned char BTUINT8;
typedef unsigned char BTUCHAR; /* extended ASII character, 0 - 255 */
typedef unsigned char BTBOOL;
typedef short BTINT16;
typedef unsigned short BTUINT16;
typedef long BTINT32;
typedef unsigned long BTUINT32;
typedef void * BTLPVOID;
typedef BTUINT32 BTDEVHDL;
typedef BTUINT32 BTSVCHDL;
typedef BTUINT32 BTCONNHDL;
typedef BTUINT32 BTSHCHDL;
typedef BTUINT32 BTSDKHANDLE;
typedef struct _BlueToothDevice
{
BTDEVHDL rmt_device_handle;
BTINT32 rmt_device_num;
BTUINT32 rmt_device_class;
BTUINT8 rmt_device_name[64];
} BLUETOOTHDEVICE;
typedef struct _BlueToothDevices
{
BTUINT32 num_rmt_devices;
BLUETOOTHDEVICE rmt_btd[100];
} BLUETOOTHDEVICES;
public ref class RemoteDeviceDiscovery
{
public:
int GetBTD(BLUETOOTHDEVICE btd);
};
在 C# 中
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BluetoothDevice
{
[MarshalAs(UnmanagedType.SysUInt)]
public UInt32 rmt_device_handle;
[MarshalAs(UnmanagedType.SysInt)]
public Int32 rmt_device_num;
[MarshalAs(UnmanagedType.SysUInt)]
public UInt32 rmt_device_class;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 248)]
public IntPtr rmt_device_name;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BluetoothDevices
{
[MarshalAs(UnmanagedType.SysUInt)]
public UInt32 num_rmt_devices;
[MarshalAs(UnmanagedType.ByValArray)]
public List<BluetoothDevice> BluetoothDeviceInfo;
}
static void Main()
{
var rd = new RemoteDeviceDiscovery();
BluetoothDevice bluetoothDevice = new BluetoothDevice();
var i = rd.GetBTD(ref bluetoothDevice);
}
错误 3 参数 1:无法从 'ConsoleWrapperTest.Program.BluetoothDevice' 转换为 'BlueSoleilWrapper._BlueToothDevice'
所以请有人指出我哪里做错了。
吉姆
更新
使用以下头代码编译 c++/cli 包装器
public ref class RemoteDeviceDiscovery
{
/* Remote Device Discovery */
public:
int^ GetBTD(_BlueToothDevices % btds);
};
和 cpp 代码
array<Byte>^ MakeManagedArray(unsigned char* input, int len)
{
array<Byte>^ result = gcnew array<Byte>(len);
for (int i = 0; i < len; i++)
{
result[i] = input[i];
}
return result;
}
int^ RemoteDeviceDiscovery::GetBTD(_BlueToothDevices % btds)
{
unsigned char name[] = "Test";
_BlueToothDevice entry;
btds.num_rmt_devices = 1;
entry.rmt_device_class = 1;
entry.rmt_device_handle = 2;
entry.rmt_device_num = 3;
entry.rmt_device_name = MakeManagedArray(name, sizeof(name));
btds.rmt_btd[0] = gcnew _BlueToothDevice();
btds.rmt_btd[0] = %entry;
return 99;
}
问题现在出在 C# 代码中
var rd = new RemoteDeviceDiscovery();
_BlueToothDevices bluetoothDevices = new _BlueToothDevices();
var i = rd.GetBTD(bluetoothDevices);
var rmt_device_handle = bluetoothDevices.rmt_btd[0].rmt_device_handle;
编译时,我得到 'GetBTD' 不受语言支持,到目前为止我所看到的所有解决方案都没有奏效。感谢任何进一步的帮助。
吉姆
我建议查看定义 class RemoteDeviceDiscovery
(Microsoft 中的 F12 Visual Studio)的程序集,看看是否可以找到该程序集对 BlueSoleilWrapper._BlueToothDevice
的定义.然后直接使用该定义。 ConsoleWrapperTest.Program.BluetoothDevice
永远不会映射到 BlueSoleilWrapper._BlueToothDevice
,无论您的定义与程序集中的定义有多接近。
您好像在使用 C++\CLI,而不是普通的 C++。如果您直接使用 RemoteDeviceDiscovery
,那么您必须实例化 BLUETOOTHDEVICE
,而不是尝试创建您自己的结构。
如果您不能使用 BLUETOOTHDEVICE
因为它不公开可见,您可以为 RemoteDeviceDiscovery
class 编写某种适配器,它将采用您的结构并将其映射到BLUETOOTHDEVICE
.
好的,得到一个有效的答案!非常感谢 rpeshkov,你为我指明了正确的方向,我很高兴我从中学到了一些东西。
在header
public ref class RemoteDeviceDiscovery
{
/* Remote Device Discovery */
public:
int GetBTD(_BlueToothDevices ^% btds);
};
在cpp代码中
int RemoteDeviceDiscovery::GetBTD(_BlueToothDevices ^% btds)
{
unsigned char name0[] = "Test0";
unsigned char name1[] = "Test1";
_BlueToothDevice^ entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 1;
entry->rmt_device_handle = 2;
entry->rmt_device_num = 3;
entry->rmt_device_name = MakeManagedArray(name0, sizeof(name0));
btds->num_rmt_devices = 2;
btds->rmt_btd[0] = gcnew _BlueToothDevice();
btds->rmt_btd[0] = entry;
entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 4;
entry->rmt_device_handle = 5;
entry->rmt_device_num = 6;
entry->rmt_device_name = MakeManagedArray(name1, sizeof(name1));
btds->rmt_btd[1] = gcnew _BlueToothDevice();
btds->rmt_btd[1] = entry;
return 99;
}
最后是 C# 代码(这当然只是开发框架的基本测试)
var rd = new RemoteDeviceDiscovery();
_BlueToothDevices bluetoothDevices = new _BlueToothDevices();
var i = rd.GetBTD(ref bluetoothDevices);
var rmt_device_handle = bluetoothDevices.rmt_btd[0].rmt_device_handle;
替换.cpp代码
int RemoteDeviceDiscovery::GetBTD(_BlueToothDevices ^% btds)
{
unsigned char name0[] = "Test0";
unsigned char name1[] = "Test1";
_BlueToothDevice^ entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 1;
entry->rmt_device_handle = 2;
entry->rmt_device_num = 3;
entry->rmt_device_name = MakeManagedArray(name0, sizeof(name0));
btds->num_rmt_devices = 2;
btds->rmt_btd[0] = gcnew _BlueToothDevice();
btds->rmt_btd[0] = entry;
entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 4;
entry->rmt_device_handle = 5;
entry->rmt_device_num = 6;
entry->rmt_device_name = MakeManagedArray(name1, sizeof(name1));
btds->rmt_btd[1] = gcnew _BlueToothDevice();
btds->rmt_btd[1] = entry;
return 99;
}
我在 2 周内阅读了大约 100 多篇关于此的帖子,并且让自己完全困惑。这是我在 BlueSoleil 堆栈上编写的包装器。
在 C++ 中
typedef char BTINT8;
typedef unsigned char BTUINT8;
typedef unsigned char BTUCHAR; /* extended ASII character, 0 - 255 */
typedef unsigned char BTBOOL;
typedef short BTINT16;
typedef unsigned short BTUINT16;
typedef long BTINT32;
typedef unsigned long BTUINT32;
typedef void * BTLPVOID;
typedef BTUINT32 BTDEVHDL;
typedef BTUINT32 BTSVCHDL;
typedef BTUINT32 BTCONNHDL;
typedef BTUINT32 BTSHCHDL;
typedef BTUINT32 BTSDKHANDLE;
typedef struct _BlueToothDevice
{
BTDEVHDL rmt_device_handle;
BTINT32 rmt_device_num;
BTUINT32 rmt_device_class;
BTUINT8 rmt_device_name[64];
} BLUETOOTHDEVICE;
typedef struct _BlueToothDevices
{
BTUINT32 num_rmt_devices;
BLUETOOTHDEVICE rmt_btd[100];
} BLUETOOTHDEVICES;
public ref class RemoteDeviceDiscovery
{
public:
int GetBTD(BLUETOOTHDEVICE btd);
};
在 C# 中
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BluetoothDevice
{
[MarshalAs(UnmanagedType.SysUInt)]
public UInt32 rmt_device_handle;
[MarshalAs(UnmanagedType.SysInt)]
public Int32 rmt_device_num;
[MarshalAs(UnmanagedType.SysUInt)]
public UInt32 rmt_device_class;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 248)]
public IntPtr rmt_device_name;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct BluetoothDevices
{
[MarshalAs(UnmanagedType.SysUInt)]
public UInt32 num_rmt_devices;
[MarshalAs(UnmanagedType.ByValArray)]
public List<BluetoothDevice> BluetoothDeviceInfo;
}
static void Main()
{
var rd = new RemoteDeviceDiscovery();
BluetoothDevice bluetoothDevice = new BluetoothDevice();
var i = rd.GetBTD(ref bluetoothDevice);
}
错误 3 参数 1:无法从 'ConsoleWrapperTest.Program.BluetoothDevice' 转换为 'BlueSoleilWrapper._BlueToothDevice'
所以请有人指出我哪里做错了。
吉姆
更新
使用以下头代码编译 c++/cli 包装器
public ref class RemoteDeviceDiscovery
{
/* Remote Device Discovery */
public:
int^ GetBTD(_BlueToothDevices % btds);
};
和 cpp 代码
array<Byte>^ MakeManagedArray(unsigned char* input, int len)
{
array<Byte>^ result = gcnew array<Byte>(len);
for (int i = 0; i < len; i++)
{
result[i] = input[i];
}
return result;
}
int^ RemoteDeviceDiscovery::GetBTD(_BlueToothDevices % btds)
{
unsigned char name[] = "Test";
_BlueToothDevice entry;
btds.num_rmt_devices = 1;
entry.rmt_device_class = 1;
entry.rmt_device_handle = 2;
entry.rmt_device_num = 3;
entry.rmt_device_name = MakeManagedArray(name, sizeof(name));
btds.rmt_btd[0] = gcnew _BlueToothDevice();
btds.rmt_btd[0] = %entry;
return 99;
}
问题现在出在 C# 代码中
var rd = new RemoteDeviceDiscovery();
_BlueToothDevices bluetoothDevices = new _BlueToothDevices();
var i = rd.GetBTD(bluetoothDevices);
var rmt_device_handle = bluetoothDevices.rmt_btd[0].rmt_device_handle;
编译时,我得到 'GetBTD' 不受语言支持,到目前为止我所看到的所有解决方案都没有奏效。感谢任何进一步的帮助。
吉姆
我建议查看定义 class RemoteDeviceDiscovery
(Microsoft 中的 F12 Visual Studio)的程序集,看看是否可以找到该程序集对 BlueSoleilWrapper._BlueToothDevice
的定义.然后直接使用该定义。 ConsoleWrapperTest.Program.BluetoothDevice
永远不会映射到 BlueSoleilWrapper._BlueToothDevice
,无论您的定义与程序集中的定义有多接近。
您好像在使用 C++\CLI,而不是普通的 C++。如果您直接使用 RemoteDeviceDiscovery
,那么您必须实例化 BLUETOOTHDEVICE
,而不是尝试创建您自己的结构。
如果您不能使用 BLUETOOTHDEVICE
因为它不公开可见,您可以为 RemoteDeviceDiscovery
class 编写某种适配器,它将采用您的结构并将其映射到BLUETOOTHDEVICE
.
好的,得到一个有效的答案!非常感谢 rpeshkov,你为我指明了正确的方向,我很高兴我从中学到了一些东西。
在header
public ref class RemoteDeviceDiscovery
{
/* Remote Device Discovery */
public:
int GetBTD(_BlueToothDevices ^% btds);
};
在cpp代码中
int RemoteDeviceDiscovery::GetBTD(_BlueToothDevices ^% btds)
{
unsigned char name0[] = "Test0";
unsigned char name1[] = "Test1";
_BlueToothDevice^ entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 1;
entry->rmt_device_handle = 2;
entry->rmt_device_num = 3;
entry->rmt_device_name = MakeManagedArray(name0, sizeof(name0));
btds->num_rmt_devices = 2;
btds->rmt_btd[0] = gcnew _BlueToothDevice();
btds->rmt_btd[0] = entry;
entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 4;
entry->rmt_device_handle = 5;
entry->rmt_device_num = 6;
entry->rmt_device_name = MakeManagedArray(name1, sizeof(name1));
btds->rmt_btd[1] = gcnew _BlueToothDevice();
btds->rmt_btd[1] = entry;
return 99;
}
最后是 C# 代码(这当然只是开发框架的基本测试)
var rd = new RemoteDeviceDiscovery();
_BlueToothDevices bluetoothDevices = new _BlueToothDevices();
var i = rd.GetBTD(ref bluetoothDevices);
var rmt_device_handle = bluetoothDevices.rmt_btd[0].rmt_device_handle;
替换.cpp代码
int RemoteDeviceDiscovery::GetBTD(_BlueToothDevices ^% btds)
{
unsigned char name0[] = "Test0";
unsigned char name1[] = "Test1";
_BlueToothDevice^ entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 1;
entry->rmt_device_handle = 2;
entry->rmt_device_num = 3;
entry->rmt_device_name = MakeManagedArray(name0, sizeof(name0));
btds->num_rmt_devices = 2;
btds->rmt_btd[0] = gcnew _BlueToothDevice();
btds->rmt_btd[0] = entry;
entry = gcnew _BlueToothDevice();
entry->rmt_device_class = 4;
entry->rmt_device_handle = 5;
entry->rmt_device_num = 6;
entry->rmt_device_name = MakeManagedArray(name1, sizeof(name1));
btds->rmt_btd[1] = gcnew _BlueToothDevice();
btds->rmt_btd[1] = entry;
return 99;
}