类型之间的转换:C++ 到 C++/CLI

Conversion between types: C++ to C++/CLI

我正在尝试将 C++ 库包装到 C++/CLI 库中以便在 C# 中使用。我在类型之间的转换时遇到问题...

C++ 函数如下所示(这是来自 MyCppLib.h 文件,我无法更改 C++ 代码):

int CppFunc(void* Handle, wchar_t* Feature, long long* Value)

我的 C++/CLI 包装函数如下所示:

#include "MyCppLib.h"
#include <msclr\marshal.h>
#include <string.h>
#include <stdlib.h>

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace msclr::interop;

namespace MyCppCliLib
{
    int CppCliFunc(IntPtr Handle, String^ Feature, long long* Value) {
        return ::CppFunc(Handle.ToPointer(), string_to_wchar(Feature), Value);
    }

    static wchar_t* string_to_wchar(String^ managedString)
    {
        marshal_context^ context = gcnew marshal_context();
        wchar_t* unmanagedString = context -> marshal_as<wchar_t*>(managedString);
        delete context;
        return unmanagedString;
    }
}

但是,我似乎无法将 String^ 编组为 wchar_t*... 错误 C2065 显示“不支持此转换”。虽然如果我用 const wchar_t* 替换它,它似乎工作...我不明白...而且我不确定我是否正确转换句柄和值类型...

如何将 C++ void*、wchar_t* 和 long long* 类型转换为 C++/CLI?

marshal_context class 是本机类型,不是垃圾收集类型。所以你不能写 gcnew marshal_context()

预期用途如下:

marshal_context context;
const wchar_t* unmanagedString = context.marshal_as<const wchar_t*>(managedString);
// use unmanagedString
// when context goes out of scope, both the context object and the memory for unmanagedString are freed

不过你有问题,你想要return一个指针。您的问题或代码中没有任何内容说明 string_to_wchar 与其调用者之间关于最终应如何释放内存的合同。我们可以通过注意到您的辅助函数太短而无法使用来避免此问题,因此您可以消除它:

#include <msclr\marshal.h>
int CppCliFunc(IntPtr Handle, String^ Feature, long long* Value)
{
    marshal_context context;
    return ::CppFunc(Handle.ToPointer(),
                     context.marshal_as<const wchar*>(Feature),
                     Value);
}

现在字符串数据在 ::CppFunc 需要时仍然存在。

但是,您需要一个非const指针。 System::String^ 意味着是不可变的(实际上并非如此,这会导致一些问题),因此 marshal_as 库会阻止您获得可写指针。不过,您可以轻松获得指向字符串副本的可写指针:

#include <msclr\marshal_cppstd.h>
int CppCliFunc(IntPtr Handle, String^ Feature, long long* Value)
{
    std::wstring strFeature{marshal_as<std::wstring>(Feature)};
    return ::CppFunc(Handle.ToPointer(),
                     &stdFeature[0],
                     Value);
}