简体   繁体   English

将结构从C ++函数返回到C#,然后返回数组UPDATE

[英]Return a struct from a c++ function to c# then an array UPDATE

I have read through maybe 100+ posts on this over 2 weeks and have got myself totally confused. 我在2个星期内阅读了100篇以上的帖子,使自己完全困惑。 This is for a wrapper i'm writing over the BlueSoleil stack. 这是我在BlueSoleil堆栈上编写的包装程序。

In c++ 在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);
};

In C# 在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);
}

Error 3 Argument 1: cannot convert from 'ConsoleWrapperTest.Program.BluetoothDevice' to 'BlueSoleilWrapper._BlueToothDevice' 错误3参数1:无法从'ConsoleWrapperTest.Program.BluetoothDevice'转换为'BlueSoleilWrapper._BlueToothDevice'

So can someone point out where I have gone wrong please. 所以有人可以指出我哪里出了问题。

Jim 吉姆

UPDATE 更新

Have the c++/cli wrapper compiling with the following header code 使用以下标头代码编译c ++ / cli包装器

public ref class RemoteDeviceDiscovery
{
    /* Remote Device Discovery */

public:

    int^ GetBTD(_BlueToothDevices % btds);
};

and cpp code 和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;
}

Problem is now in the C# code 现在问题在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;

When compiling I get 'GetBTD' is not supported by the language and everything I have seen so far as solutions hasn't worked. 编译时,该语言不支持“ GetBTD”,到目前为止,我所看到的一切都无法解决。 Appreciate any further assistance. 感谢任何进一步的协助。

Jim 吉姆

Seems like you're using C++\\CLI, not plain C++. 似乎您使用的是C ++ \\ CLI,而不是纯C ++。 If you're using RemoteDeviceDiscovery directly then you have to instantiate BLUETOOTHDEVICE , not trying to create your own structure. 如果直接使用RemoteDeviceDiscovery ,则必须实例化BLUETOOTHDEVICE ,而不是尝试创建自己的结构。

If you can't use BLUETOOTHDEVICE because it's not publicly visible, you can write some sort of adapter for RemoteDeviceDiscovery class that will be taking your structure and mapping it on BLUETOOTHDEVICE . 如果由于无法公开显示而无法使用BLUETOOTHDEVICE ,则可以为RemoteDeviceDiscovery类编写某种适配器,它将采用您的结构并将其映射到BLUETOOTHDEVICE

Ok, got a working answer ! 好的,有一个可行的答案! Many thanks to rpeshkov you pointed me in the right direction and i'm glad I learnt something from it all. 非常感谢rpeshkov,您为我指明了正确的方向,我很高兴从中学到了一些东西。

In the header 在标题中

public ref class RemoteDeviceDiscovery
{
    /* Remote Device Discovery */
public:
    int GetBTD(_BlueToothDevices ^% btds);
};

In the cpp code 在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;
}

and finally in the C# code (this is of course just a bare bones test to development a framework) 最后是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;

I suggest looking in the assembly that defines the class RemoteDeviceDiscovery (F12 in Microsoft Visual Studio), and see if you can find that assembly's definition of BlueSoleilWrapper._BlueToothDevice . 我建议查看定义了类RemoteDeviceDiscovery的程序集(在Microsoft Visual Studio中为F12),看看是否可以找到该程序集的BlueSoleilWrapper._BlueToothDevice定义。 Then use that definition directly. 然后直接使用该定义。 ConsoleWrapperTest.Program.BluetoothDevice will never map to BlueSoleilWrapper._BlueToothDevice , regardless of how close your definition matches the one in the assembly. ConsoleWrapperTest.Program.BluetoothDevice永远不会映射到BlueSoleilWrapper._BlueToothDevice ,无论您的定义与程序集中的定义多么接近。

Replacement .cpp code 替换.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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM