所以我有一个包含在 *.dll 中的 C++ API,我想使用 C# 应用程序调用 API 中的方法。
到目前为止,我已经创建了一个包含 native C++ API 的 C++/CLR 项目,并设法创建了一个类似于以下内容的“桥接”类:
// ManagedBridge.h
#include <CoreAPI.h>
using namespace __CORE_API;
namespace ManagedAPIWrapper
{
public ref class Bridge
{
public:
int bridge_test(void);
int bridge_test2(api_struct* temp);
}
}
.
// ManagedBridge.cpp
#include <ManagedBridge.h>
int Bridge::bridge_test(void)
{
return test();
}
int Bridge::bridge_test2(api_struct* temp)
{
return test2(temp);
}
我还有一个 C# 应用程序,它引用了 C++/CLR“Bridge.dll”,然后使用其中包含的方法。我对此有很多问题:
- 我不知道如何在 C# 程序中调用 bridge_test2,因为它不知道 api_struct 实际上是什么。我知道我需要在某处编码对象,但我是在 C# 程序中还是在 C++/CLR 桥中进行编码?
- 这似乎是一种非常公开 API 中所有方法的冗长方式,难道没有一种更简单的方法我错过了吗? (这不使用 P/Invoke!)
编辑: 好的,由于下面的回复,我现在已经掌握了基础知识,但是我的结构(在本例中称为“api_struct2”)在C++ native 代码,如下所示:
typedef struct
{
enum_type1 eEnumExample;
union
{
long lData;
int iData;
unsigned char ucArray[128];
char *cString;
void *pvoid;
} uData;
} api_struct2;
我想我已经弄清楚如何让枚举工作;我已经在托管代码中重新声明了它,并且正在执行“native_enum test = static_cast(eEnumExample)”以将托管版本切换到 native 。
但是 union 让我难住了,我真的不确定如何攻击它。有人有想法吗?
最佳答案
是的,您正在通过引用传递非托管结构。这是 C# 程序的问题,指针与垃圾回收非常不兼容。不包括它可能也没有结构声明的事实。
您可以通过声明结构的托管版本来解决它:
public value struct managed_api_struct {
// Members...
};
现在您可以将方法声明为
int bridge_test2(managed_api_struct temp); // pass by value
或
int bridge_test2(managed_api_struct% temp); // pass by reference
如果结构有超过 4 个字段(~16 字节),请选择后者。该方法需要将结构成员一个接一个地复制到非托管 api_struct 中并调用非托管类方法。不幸的是,这是必要的,因为托管结构的内存布局是不可预测的。
这一切都非常机械化,您可能会得到帮助 from SWIG .我自己没用过,不确定它是否足够智能来处理传递的结构。
一种完全不同的方法是通过为包装类提供一个构造函数和/或允许您构建 api_struct 内容的属性来使包装类更清晰。或者您可以为该结构声明一个包装器 ref 类,就像您在托管代码中所做的那样。
关于c# - 向 C# 公开 C++ API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2606216/