如何将C++对象传递给 C#

How to pass C++ Object to C#

本文关键字:对象 C++      更新时间:2023-10-16

向处理过C++和 C# 的有经验的人寻求帮助

我现在正在编写一个 C# 项目,该项目需要调用内部库中现有的 C++ 函数,并遇到了一些困难。

C++ 代码函数标头(无法更改(

typedef int (*PTR_func) 
(const char*             param1,      // input
const char*             param2,      // input
VirtualInternalString&  po_output);  // Third param is actually the output

内部字符串对象的C++代码类(无法更改(

namespace InternalLib
{
class VirtualInternalString
{
public :
virtual ~VirtualInternalString(){};
virtual void _cdecl SetString(const char *) =0;
virtual const char * _cdecl c_str() const =0;
};
class SafeInternalString :public VirtualInternalString
{
public :
SafeInternalString():TheString(""){};
virtual ~SafeInternalString(){};
virtual void _cdecl SetString(const char *  chararray) { TheString = chararray;};
virtual const char * _cdecl c_str() const { return TheString.c_str() ;} ;           // This is the std::string
protected:
std::string TheString;
};
class SafePtrString :public VirtualInternalString
{
public :
SafePtrString():PtrString(0){};
SafePtrString(std::string &str):PtrString(&str){};
virtual ~SafePtrString(){}; 
virtual void _cdecl SetString(const char *  chararray) { (* PtrString) = chararray;};
virtual const char * _cdecl c_str() const { return PtrString->c_str() ;} ;
protected :
std::string * PtrString;
};
}

现在,我必须在 C# 代码中使用此"func"。我可以正确调用和使用C++函数,但是在输出返回(第三个参数(期间出现问题。它应该是与问题相关的返回类型。

C#(可以更改(

[DllImport("xxxxlib", CallingConvention = CallingConvention.Cdecl)]
private extern static int func(string param1, 
string param2, 
[MarshalAs(UnmanagedType.LPStr)] StringBuilder res); // problem here

我知道我必须创建一个适当的包装器来将 c++ 对象解码为 C# 字符串,但我以前没有这方面的经验。我已经尝试了互联网上的几种解决方案,但不起作用。

有人知道我如何实现这一点吗?你介意给我看一些简单的 C# 框架代码吗?

如果您只更改 C# 端,Vasek 的可能重复将不起作用。但是您可以做的是在C++中创建包装器,这些包装器创建具有关联length参数的原始char *

创建一个附加的C++标头和源,其中包含:

int func 
(const char*             param1,      // input
const char*             param2,      // input
char*                   po_output,   // Third param is actually the output
int                     length);     // Length of the buffer allocated by caller  

然后你让你的func打电话PTR_func.

在这种情况下,我认为使用 C++/CLI 确实有意义。你可能希望在本机 C++ DLL 和 C# 代码之间构建一个微小的C++/CLI 桥接。

C++/CLI 层负责将自定义C++字符串类作为 DLL 函数的输出参数,并从此自定义字符串转换为 C#/.NET 字符串对象。

您的自定义C++字符串类似乎包装了std::string;另一方面,C#/.NET 字符串使用 Unicode UTF-16 作为其文本编码,因此您可能需要在 Unicode UTF-8(存储在std::string和自定义字符串类中(和 UTF-16(用于 C#/.NET 字符串(之间进行转换。

同样,还需要在此 C++/CLI 桥接层中将 C# UTF-16 字符串转换为 UTF-8,并将这些 UTF-8 编码的字符串作为const char*输入参数传递给本机 DLL 函数。

使用 COM 并从 C# 代码中使用C++。仅当您在Windows平台上时。

根据过去的经验,我确实使用SWIG工具来实现生成包装器 它支持C++到多种语言的包装生成,其中Java是最受欢迎的语言 有一个很棒的教程 - http://www.swig.org/tutorial.html 还支持 C# - http://www.swig.org/Doc3.0/CSharp.html

/* InternalLib.i */
%module InternalLib
%{
/* include header with a VirtualInternalString class*/
#include "InternalLib.h"
%}

然后调用 swig 生成包装器文件:

swig -csharp InternalLib.i