类型之间的转换: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);
}
我正在尝试将 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);
}