在项目中,遇到C++ 与 c#编写的模块之间的相互调用。
分两种情况:
1 c#模块使用C++模块的DLL(导出C API函数), 只需简单引用C++模块的 DLL即可。
2 c++模块调用c#模块DLL时,则需要使用一个适配模块(adapter), 它提供两个作用:1 导出C API供c++模块调用; 2 加戴加载C#模块DLL,并通过.NET基础时库的函数,获得C#类或函数名供调用。
示例说明:
C++ 工程 : SP (编译生成SP.dll)
some_dev.h:
class some_dev
{
public:
bool init_hook();
};
some_dev.cpp:
bool some_dev::init_hook()
{
return init_adapter("", "http://192.168.1.28/query_event.asmx"); // call C# function by C++
}
extern "C" __declspec(dllexport) on_recv(const char* data)
{
;
}
(managed C++ / clr 支持)工程: adapter (编译生成:adapter.dll )
adapter.h:
#ifdef WIN32
#ifdef ADAPTER_EXPORTS
#define ADAPTER_API __declspec(dllexport)
#else
#define ADAPTER_API __declspec(dllimport)
#endif
#else
#ifdef ADAPTER_EXPORTS
#define ADAPTER_API __attribute__((visibility("default")))
#else
#define ADAPTER_API
#endif
#endif
#include <string>
extern "C" ADAPTER_API bool init_adapter(const char* curr_path, const char* web_service_url);
adapter.cpp:
using namespace System;
using namespace System::Reflection;
namespace adapter {
public ref class wrapper
{
private:
static Assembly^ dll_ = nullptr;
static Assembly^ dll_ = nullptr;
static MethodInfo^ on_recv_cb_method_ = nullptr;
public:
static bool init(const char* dev_path, const char* web_service_url)
{
String^ path = gcnew String(dev_path);
path += "\\web_service_client_impl.dll";
try
{
wrapper::dll_ = Assembly::LoadFrom(path);
String^ url_string = gcnew String(web_service_url);
Type^ classType = wrapper::dll_->GetType("web_service_client_impl.api_wrapper");
MethodInfo^ method = classType->GetMethod("init");
method->Invoke((Type^)nullptr, gcnew array<Object^>(1){url_string });
}
catch (System::Exception^ e)
{
return false;
}
return true;
}
};
}
extern "C" ADAPTER_API bool init_adapter(const char* curr_path, const char* web_service_url)
{
return adapter::wrapper::init(curr_path, web_service_url);
}
C# 工程 : web_service (生成 web_service.dll)
namespace web_service_client_impl
{
internal static class SP_helper
{
[DllImport("SP.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void on_recv(byte[] data);
}
public class api_wrapper
{
static private string web_service_url_;
static public void init(string web_service_url)
{
api_wrapper.web_service_url_ = web_service_url;
}
public void on_recv(byte[] data)
{
SP_helper.on_recv(data); // call C API in SP.dll by C#
}
}
}