在 c# 代码中使用在 c++ dll 中定义的类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/315051/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using a class defined in a c++ dll in c# code
提问by Dan Vogel
I have a dll that was written in c++, I need to use this dll in my c# code. After searching I found that using P/Invoke would give me access to the function I need, but these functions are defined with in a class and use non-static private member variables. So I need to be able to create an instance of this class to properly use the functions. How can I gain access to this class so that I can create an instance? I have been unable to find a way to do this.
我有一个用 c++ 编写的 dll,我需要在我的 c# 代码中使用这个 dll。搜索后我发现使用 P/Invoke 可以让我访问我需要的函数,但这些函数是在一个类中定义的,并使用非静态私有成员变量。所以我需要能够创建这个类的一个实例来正确使用这些函数。我怎样才能访问这个类以便我可以创建一个实例?我一直无法找到一种方法来做到这一点。
I guess I should note that the c++ dll is not my code.
我想我应该注意 c++ dll 不是我的代码。
采纳答案by JaredPar
There is no way to directly use a C++ class in C# code. You can use PInvoke in an indirect fashion to access your type.
无法在 C# 代码中直接使用 C++ 类。您可以以间接方式使用 PInvoke 来访问您的类型。
The basic pattern is that for every member function in class Foo, create an associated non-member function which calls into the member function.
基本模式是为类 Foo 中的每个成员函数创建一个关联的非成员函数,该函数调用该成员函数。
class Foo {
public:
int Bar();
};
extern "C" Foo* Foo_Create() { return new Foo(); }
extern "C" int Foo_Bar(Foo* pFoo) { return pFoo->Bar(); }
extern "C" void Foo_Delete(Foo* pFoo) { delete pFoo; }
Now it's a matter of PInvoking these methods into your C# code
现在是将这些方法 PInvoking 到您的 C# 代码中的问题
[DllImport("Foo.dll")]
public static extern IntPtr Foo_Create();
[DllImport("Foo.dll")]
public static extern int Foo_Bar(IntPtr value);
[DllImport("Foo.dll")]
public static extern void Foo_Delete(IntPtr value);
The downside is you'll have an awkward IntPtr to pass around but it's a somewhat simple matter to create a C# wrapper class around this pointer to create a more usable model.
缺点是你将有一个笨拙的 IntPtr 来传递,但围绕这个指针创建一个 C# 包装类来创建一个更有用的模型是一件有点简单的事情。
Even if you don't own this code, you can create another DLL which wraps the original DLL and provides a small PInvoke layer.
即使您不拥有此代码,您也可以创建另一个 DLL 来包装原始 DLL 并提供一个小的 PInvoke 层。
回答by Brian
You may need to write an intermediary DLL (in C++, perhaps) that handles this for you and exposes the interface you need. Your DLL would be in charge of loading the 3rd party DLL, creating an instance of this C++ object, and exposing its member functions as needed via whatever API you design. You would then use P/Invoke to get at your API and cleanly manipulate the object.
您可能需要编写一个中间 DLL(可能使用 C++)来为您处理此问题并公开您需要的接口。您的 DLL 将负责加载第 3 方 DLL,创建此 C++ 对象的实例,并根据需要通过您设计的任何 API 公开其成员函数。然后您将使用 P/Invoke 来获取您的 API 并干净地操作该对象。
Note: For the API of your DLL, try keeping the data types limited to primitives (long, int, char*, etc.) to prevent module boundary issues.
注意:对于 DLL 的 API,请尝试将数据类型限制为基元(long、int、char* 等),以防止出现模块边界问题。
回答by Paul Kapustin
I agree with JaredPar. Creating instances of unmanaged classes in managed code should not be possible.
我同意 JaredPar。在托管代码中创建非托管类的实例应该是不可能的。
Another thing is - if you could recompile the DLL in managed C++ or make a COM component out of it, it would be much easier/
另一件事是 - 如果您可以在托管 C++ 中重新编译 DLL 或从中制作一个 COM 组件,它会容易得多/
回答by Dmitry Khalatov
回答by Joris Timmermans
The way I've done this is by creating a thin Managed C++ wrapper around my unmanaged C++ DLL. The managed wrapper contains "proxy" classes that wrap around the unmanaged code exposing the interface that's needed by the .NET application. This is a bit of double work but it allows quite seamless operation in normal environments. Things do get trickier with dependencies in some circumstances (such as ASP.NET) but you will probably not run into that.
我这样做的方法是在我的非托管 C++ DLL 周围创建一个薄的托管 C++ 包装器。托管包装器包含环绕非托管代码的“代理”类,这些代码公开 .NET 应用程序所需的接口。这是一项双重工作,但它允许在正常环境中进行相当无缝的操作。在某些情况下(例如 ASP.NET)依赖项确实会变得更加棘手,但您可能不会遇到这种情况。
回答by patrick
myfile.i
我的文件
%module learnaboutswig
class A
{
public:
void boringfunction(char *charstr);
};
download swig from swig.org
从 swig.org 下载 swig
swig -c++ -csharp myfile.i
swig -c++ -csharp myfile.i
look at the output, see if it will work for you.
看看输出,看看它是否适合你。
回答by Amir Twito
Marshal C++ Class and use the PInvoke
元帅 C++ 类并使用 PInvoke
C++ Code ,ClassName.h
C++ 代码,ClassName.h
class __declspec(dllexport) CClassName
{
public:
CClassName();
~CClassName();
void function();
};
C++ Code, ClassName.cpp
C++ 代码,ClassName.cpp
CClassName::CClassName()
{
}
CClassName::~CClassName()
{
}
void CClassName::function()
{
std::cout << "Bla bla bla" << std::endl;
}
C++ Code, ClassNameCaller.h file for the caller function
C++ 代码,调用函数的 ClassNameCaller.h 文件
#include "ClassName.h"
#ifdef __cplusplus
extern "C" {
#endif
extern __declspec(dllexport) CClassName* CreateClassName();
extern __declspec(dllexport) void DisposeClassName(CClassName* a_pObject);
extern __declspec(dllexport) void function(CClassName* a_pObject);
#ifdef __cplusplus
}
#endif
C++ Code, ClassNameCaller.cpp file for the caller function
C++ 代码,调用函数的 ClassNameCaller.cpp 文件
#include "ClassNameCaller.h"
CClassName* CreateClassName()
{
return new CClassName();
}
void DisposeClassName(CClassName* a_pObject)
{
if(a_pObject!= NULL)
{
delete a_pObject;
a_pObject= NULL;
}
}
void function(CClassName* a_pObject)
{
if(a_pObject!= NULL)
{
a_pObject->function();
}
}
C# code
C# 代码
[DllImport("ClassNameDll.dll")]
static public extern IntPtr CreateClassName();
[DllImport("ClassNameDll.dll")]
static public extern void DisposeClassName(IntPtr pClassNameObject);
[DllImport("ClassNameDll.dll")]
static public extern void CallFunction(IntPtr pClassNameObject);
//use the functions
IntPtr pClassName = CreateClassName();
CallFunction(pClassName);
DisposeClassName(pClassName);
pClassName = IntPtr.Zero;