虽然懒得我写了一个例子,但我还是会发布它以防万一......
编写包装器以访问您自己的库的过程与访问标准 .Net 库之一相同。
一个名为 CsharpProject 的项目中的示例 C# 类代码:
using System;
namespace CsharpProject {
public class CsharpClass {
public string Name { get; set; }
public int Value { get; set; }
public string GetDisplayString() {
return string.Format("{0}: {1}", this.Name, this.Value);
}
}
}
您将创建一个托管 C++ 类库项目(例如 CsharpWrapper)并将您的 C# 项目添加为对其的引用。为了在内部使用和引用项目中使用相同的头文件,您需要一种使用正确 declspec 的方法。这可以通过定义预处理器指令(在这种情况下为CSHARPWRAPPER_EXPORTS)并使用#ifdef 在头文件中的C/C++ 接口中设置导出宏来完成。非托管接口头文件必须包含非托管内容(或已被预处理器过滤掉)。
非托管C++接口头文件(CppInterface.h):
#pragma once
#include <string>
// Sets the interface function's decoration as export or import
#ifdef CSHARPWRAPPER_EXPORTS
#define EXPORT_SPEC __declspec( dllexport )
#else
#define EXPORT_SPEC __declspec( dllimport )
#endif
// Unmanaged interface functions must use all unmanaged types
EXPORT_SPEC std::string GetDisplayString(const char * pName, int iValue);
然后您可以创建一个内部头文件,以便能够包含在您的托管库文件中。这将添加 using namespace 语句,并且可以包含您需要的辅助函数。
托管 C++ 接口头文件 (CsharpInterface.h):
#pragma once
#include <string>
// .Net System Namespaces
using namespace System;
using namespace System::Runtime::InteropServices;
// C# Projects
using namespace CsharpProject;
//////////////////////////////////////////////////
// String Conversion Functions
inline
String ^ ToManagedString(const char * pString) {
return Marshal::PtrToStringAnsi(IntPtr((char *) pString));
}
inline
const std::string ToStdString(String ^ strString) {
IntPtr ptrString = IntPtr::Zero;
std::string strStdString;
try {
ptrString = Marshal::StringToHGlobalAnsi(strString);
strStdString = (char *) ptrString.ToPointer();
}
finally {
if (ptrString != IntPtr::Zero) {
Marshal::FreeHGlobal(ptrString);
}
}
return strStdString;
}
然后您只需编写执行包装的接口代码。
托管 C++ 接口源文件 (CppInterface.cpp):
#include "CppInterface.h"
#include "CsharpInterface.h"
std::string GetDisplayString(const char * pName, int iValue) {
CsharpClass ^ oCsharpObject = gcnew CsharpClass();
oCsharpObject->Name = ToManagedString(pName);
oCsharpObject->Value = iValue;
return ToStdString(oCsharpObject->GetDisplayString());
}
然后只需在非托管项目中包含非托管标头,告诉链接器在链接时使用生成的 .lib 文件,并确保 .Net 和包装 DLL 与非托管应用程序位于同一文件夹中。
#include <stdlib.h>
// Include the wrapper header
#include "CppInterface.h"
void main() {
// Call the unmanaged wrapper function
std::string strDisplayString = GetDisplayString("Test", 123);
// Do something with it
printf("%s\n", strDisplayString.c_str());
}