用c#中的char*调用一个c++函数
本文关键字:一个 c++ 函数 中的 char 调用 | 更新日期: 2023-09-27 18:25:29
我有一个CLR C++dll,它重写了一个静态C++库。我有以下课程:
#pragma once
#include <windows.h>
#include <sddl.h>
#include <LibEx.h>
using namespace System;
#using <mscorlib.dll>
namespace LIB_WrapperNamespace {
public ref class LIB_WrapperClass
{
public:
BOOL WINAPI T_LibEx_ConsoleConnect(IN DWORD num1, IN LPWSTR Name)
{
return LibEx_ConsoleConnect(num1,Name);
}
};
}
在C#中,我添加了对库的引用
LIB_WrapperNamespace.LIB_WrapperClass myLib = new LIB_WrapperNamespace.LIB_WrapperClass();
现在如何调用这个函数,如何将字符串发送到char*?来自C#:
string myName = "NAME";
myLib.T_LibEx_ConsoleConnect(1,**myName**);
API应该将该参数公开为wchar_t*
,因此您需要在C#中提供一个指针值。尝试以下
IntPtr ptr = IntPtr.Zero;
try {
ptr = Marshal.StringToCoTaskMemUni("NAME");
unsafe {
myLib.T_LibEx_Consoleconnect(1, (char*)(ptr.ToPointer()));
}
} finally {
if (ptr != IntPtr.Zero) {
Marshal.FreeCoTaskMem(ptr);
}
}
不幸的是,由于您已经使用原始指针值公开了该方法,因此如果没有unsafe
代码,就无法从C#中使用该方法。另一种方法是暴露过载,比如string^
。这在C#中是可用的,并且C++/CLI代码可以处理从string^
到LPWSTR
的编组
BOOL WINAPI T_LibEx_ConsoleConnect(DWORD num1, String^ Name) {
IntPtr ip = Marshal::StringToHGlobalUni(Name);
BOOL ret = T_LibEx_ConsoleConnect(num1, static_cast<LPWSTR>(ip.ToPointer()));
Marshal::FreeHGlobal(ip);
return ret;
}
// From C#
myLib.T_LibEx_ConsoleConnect(1, "NAME");
当您将封送处理问题"暴露"给包装器的用户时,为什么要构建C++''CLI项目来包装某些内容?C++''CLI的思想是将封送处理问题隐藏在包装器中。您应该为.NET:原生地声明函数
#pragma once
#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <msclr'marshal_cppstd.h>
#include <vector>
namespace ClassLibrary2 {
public ref class Class1
{
public:
//Expose .NET types to .NET users.
System::Boolean T_LibEx_ConsoleConnect(System::UInt64 num1, System::String^ Name);
};
}
当你觉得合适的时候,实现这个包装器函数,它可能看起来像这样:
#include "ClassLibrary2.h"
namespace ClassLibrary2 {
System::Boolean Class1::T_LibEx_ConsoleConnect(
System::UInt64 num1,
System::String^ Name)
{
//Initialize marshaling infrastructure. You can use its instance many times
//through out life span of your application.
msclr::interop::marshal_context^ marshalContext = gcnew msclr::interop::marshal_context();
//Turn System::String into LPWSTR. Keep in mind that you are now the owner of
//memory buffer allocated for unmanagedName. You need to release it somewhere.
const wchar_t* clsConstChars = marshalContext->marshal_as<const wchar_t*>(Name);
LPWSTR unmanagedName = const_cast<LPWSTR>(clsConstChars);
//System::UInt64 num1 will be marshalled to DWORD natively by compiler.
return LibEx_ConsoleConnect(num1, unmanagedName);
}}