为了使C wrapper
一个C++
类在例如C#
应用程序中使用,您可以执行以下操作。
在 Visual Studio 中选择Win32 Console Application
并输入名称,然后单击下一步,然后在下一个窗格中选择DLL
并单击完成。完成后,您会看到一个包含 3 个文件的 DLL 项目。
testdll.h
testdll.cpp
dllmain
testdll.h
删除您的和文件中存在的所有testdll.cpp
内容,并将以下内容分别复制到每个文件中。将这些行添加到您的 testdll.h
// Our C wrapper for creating a dll to be used in C# apps
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TESTDLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TESTDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C"
{
TESTDLL_API int OurTestFunction(int x, int y);
}
它在这个外部“C”块内,您可以在其中定义接口、访问类成员函数的函数。注意TESTDLL
函数原型之前的内容。您的所有功能都必须按此进行。
将这些添加到您的 testdll.cpp 文件中:
#include "testdll.h"
#include "ourClass.h"
#define DLL_EXPORT
extern "C"
{
OurClass ourObject;
TESTDLL_API int OurTestFunction(int x, int y)
{
return ourObject.Add(x,y);
}
}
您编译它并获得一个可用于 C# 应用程序的基于 C 的 dll。
不过有几点需要注意,更重要的是:
- 您需要了解您用作代理的代码 - 我的意思是您内部的函数定义
testdll.h
,必须只能使用 C 兼容类型,毕竟它是 C 而不是 C++。
- 是您希望能够分配类的新对象,而不是仅使用一个全局对象来访问所有方法。
为此,如果您需要在成员函数之间传递您的类对象,您需要首先将其转换为void*
C 可以理解的,然后传递它并使用它来访问您的任何成员函数。
例如testdll.h
,为了使用户能够间接管理对象,我会在我的内部有这样的东西:
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C"
{
TESTDLL_API int OurTestFunction(int x, int y);
TESTDLL_API void* CreateHandle();
TESTDLL_API void* GetCurrentHandle();
TESTDLL_API void DisposeCurrentHandle();
TESTDLL_API void SetCurrentHandle(void* handle);
TESTDLL_API void* GetHandle();
TESTDLL_API void DisposeHandle(void*);
TESTDLL_API void DisposeArrayBuffers(void);
}
在我的 testdll.cpp 中,我将它们定义为:
#include "testdll.h"
#include "ourClass.h"
#define DLL_EXPORT
extern "C"
{
OurClass *ourObject;
TESTDLL_API int OurTestFunction(int x, int y)
{
//return ourObject.Add(x,y); -- not any more !!
ourObject = reinterpret_cast<OurClass *>(GetHandle());
}
//Handle operations
TESTDLL_API void* CreateHandle()
{
if (ourObject == nullptr)
{
ourObject = new OurClass ;
}
else
{
delete ourObject ;
ourObject = new OurClass ;
}
return reinterpret_cast<void*>(ourObject);
}
TESTDLL_API void* GetCurrentHandle()
{
return reinterpret_cast<void*>(ourObject );
}
TESTDLL_API void DisposeCurrentHandle()
{
delete ourObject ;
ourObject = nullptr;
}
TESTDLL_API void SetCurrentHandle(void* handle)
{
if (handle != nullptr)
{
ourObject = reinterpret_cast<OurClass *>(handle);
}
else
{
ourObject = new OurClass ;
}
}
//factory utility function
TESTDLL_API void* GetHandle()
{
void* handle = GetCurrentHandle();
if (handle != nullptr)
{
return handle;
}
else
{
ourObject = new OurClass ;
handle = reinterpret_cast <void*>(ourObject );
}
return handle;
}
CDLL_API void DisposeHandle(void* handle)
{
OurClass * tmp = reinterpret_cast<OurClass *>(handle);
delete tmp;
}
TESTDLL_API void DisposeArrayBuffers(void)
{
ourObject = reinterpret_cast<OurClass *>(GetHandle());
return ourObject ->DisposeBuffers();//This is a member function defined solely for this purpose of being used inside this wrapper to delete any allocated resources by our class object.
}
}
当我们编译它时Dll
,我们可以很容易地在我们的 C# 应用程序中使用它。在能够使用我们在这个 dll 中定义的函数之前,我们需要使用适当[ImportDll()]
的 . 因此,对于我们的 TestDll,我们将编写:
[DllImport(@"TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int OurTestFunction(int firstNumber,int secondNumber);
最后像这样使用它:
private void btnReadBigram_Click(object sender, EventArgs e)
{
int x = OurTestFunction(10,50);
MessageBox.Show(x.ToString());
}
这就是我所做的一切,以使我的 C++ 类成员函数可以在 C# 应用程序中轻松访问。
注意:
在编译 C# 应用程序时,请确保您没有选择x86
编译项目的平台AnyCpu
。您可以通过属性更改平台。
注 2:
要了解如何为原生 C++ 类创建 C++/CLI 包装器,请阅读:C++/CLI wrapper for your native C++ class。