C++ cli 将简单和复杂数据类型编组到对象^%/void*

C++ cli 将简单和复杂数据类型编组到对象^%/void*,c++-cli,marshalling,wrapper,C++ Cli,Marshalling,Wrapper,我想这对于C++/CLI专家来说很简单 < >我正在创建一个包装器,它将把高性能C++原生类暴露给C.ViWrFrm应用程序。 对于简单的已知对象,一切都很顺利,我还可以包装一个回调函数来委托。但现在我有点困惑 本机C++类有以下方法: int GetProperty(int propId, void* propInOut) 起初我以为我可以使用void*作为IntPtr,但后来我发现我需要从C#访问它。所以我想到了一个包装器方法: int GetProperty(int propId, Ob

我想这对于C++/CLI专家来说很简单

< >我正在创建一个包装器,它将把高性能C++原生类暴露给C.ViWrFrm应用程序。 对于简单的已知对象,一切都很顺利,我还可以包装一个回调函数来委托。但现在我有点困惑

本机C++类有以下方法:

int GetProperty(int propId, void* propInOut)
起初我以为我可以使用void*作为IntPtr,但后来我发现我需要从C#访问它。所以我想到了一个包装器方法:

int GetProperty(int propId, Object^ propInOut)
<> P>但我通过C++源代码查看了,发现该方法需要修改对象。因此,显然我需要:

int GetProperty(int propId, Object^% propInOut)
现在我无法将对象传递给本机方法,因此我需要知道如何在包装器中处理它们。由于调用者应该总是知道他/她正在传递/接收什么样的数据,我声明了一个包装器:

int GetProperty(int propId, int dataType, Object^% propInOut)
我想,我可以用它来传递引用和值类型,例如,像这样的int:

Object count = 100; // yeah, I know boxing is bad but this will not be real-time call anyway
myWrapper.GetProperty(Registry.PROP_SMTH, DATA_TYPE_INT, ref count);
我刚刚为我需要的所有数据类型添加了一组数据类型常量:

DATA_TYPE_INT, DATA_TYPE_FLOAT, DATA_TYPE_STRING, DATA_TYPE_DESCRIPTOR, DATA_TYPE_BYTE_ARRAY
(DATA_TYPE_DESCRIPTOR是一个简单的结构,有两个字段:int Id和wstring Description-这个类型也将被包装,所以我猜封送将是简单的来回复制数据;所有本机字符串都是Unicode)

现在,问题是-如何为所有这5种类型实现包装器方法? 当我可以将对象^%强制转换为某个对象(int,float安全吗?)并传递到本机方法时,何时需要使用pin_ptr,何时需要更复杂的封送到本机并返回

int GetProperty(int propId, int dataType, Object^% propInOut)
{
    if(dataType == DATA_TYPE_INT)
    {
        int* marshaledPropInOut = ???
        int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
        // need to do anything more?
        return result;
    }
else
    if(dataType == DATA_TYPE_FLOAT)
    {
        float* marshaledPropInOut = ???
        int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
        // need to do anything more ?
        return result;
    }
else
    if(dataType == DATA_TYPE_STRING)
    {
        // will pin_ptr be needed or it is enough with the tracking reference in the declaration?
        // the pointers won't get stored anywhere in C++ later so I don't need AllocHGlobal
        int result = nativeObject->GetProperty(propId, (void*)marshaledPropInOut);
        // need to do anything more?
        return result;
    }
else
    if(dataType == DATA_TYPE_BYTE_ARRAY)
    {
         // need to convert form managed byte[] to native char[] and back; 
         // user has already allocated byte[] so I can get the size of array somehow

         return result;
    }
else
    if(dataType == DATA_TYPE_DESCRIPTOR)
    {
         // I guess I'll have to do a dumb copying between native and managed struct, 
         // the only problem is pinning of the string again before passing to the native

         return result;
    }

    return -1;
}

另外,也许有一种更优雅的解决方案可以将这个void*方法包装成许多可能的数据类型?

将C#对象等同于void*并不一定有意义。没有任何方法可以封送任意数据。即使有了对象,C仍然知道它下面是什么类型,并且封送处理发生了——这意味着从C++世界到C语言的转换,反之亦然——数据类型需要被知道。void*只是指向完全未知类型内存的指针,那么如何将其转换为必须知道类型的对象呢

如果你描述的类型有限,可以从C语言世界中传递,最好在你的C++ /CLI代码中进行多个重载,每个代码都使用其中一种类型,然后你可以把传入的类型(如果需要的话)转换成空洞*,传递给C++函数,空缺。然后根据类型进行封送处理

您可以实现所列的case语句,但如果无法处理传入的类型,该怎么办?从C#调用函数的人无法知道什么类型是可接受的,编译器也无法帮助您找出您做错了什么