【问题标题】:Conversion between types: C++ to C++/CLI类型之间的转换:C++ 到 C++/CLI
【发布时间】:2021-12-06 15:49:09
【问题描述】:

我正在尝试将 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?

【问题讨论】:

标签: c# c++ c++-cli


【解决方案1】:

marshal_context 类是本机类型,而不是垃圾收集类型。所以你不能写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

你有一个问题,你想返回一个指针。您的问题或代码中没有任何关于 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);
}

【讨论】:

  • 谢谢你的解释,这开始更有意义了......但首先,奇怪的是我不能写 gcnew marshal_context() 因为我直接从微软找到了这个例子(@987654321 @,见页面底部)...其次,我尝试了您的代码,但在 wchar_t* 转换时仍然遇到相同的错误:C4996 和 C2065“库不支持此转换或不包含所需的头文件.", "不支持转换,未声明的标识符".
  • @bricx:已编辑,立即尝试。
  • 完美,可以,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 2013-03-27
  • 2014-02-13
  • 1970-01-01
相关资源
最近更新 更多