C库的C ++ / CLI类包装器
我使用C ++ / CLI封装了一个C库。 C库设计用于从非托管C ++类中使用。 这意味着库函数接受一个C ++对象指针,然后在回调中提供该指针。 这使回调代码可以将请求重定向到调用C ++对象中的适当事件函数。
实际功能非常重要,所以我将问题空间简化为几个基本项目:
// C library function signature
void CLibFunc(CLIBCALLBACK *callback, void *caller);
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C callback implementation
int CallBackImpl(int param1, void* caller)
{
// Need to call the ManagedCaller's EventFunction from here
// ???
}
// C++/CLI caller class
public ref class ManagedCaller
{
public:
void CallerFunction(void)
{
// Call the C library function
// Need to pass some kind of this class pointer that refers to this object
CLibFunc(CallBackImpl, ????);
}
void EventFunction(param1)
{
}
}
现在C库函数需要从托管的C ++类中调用。 在C ++ / CLI下,垃圾收集器在内存中移动对象,因此传递一个简单的固定指针到类不再工作。 我可以通过固定对象来解决问题,但不建议这样做,因为这会导致内存碎片。 看起来,另一种选择是使用auto_gcroot指针,但我对托管C ++来说是相当新的,我不知道如何使其工作。
有谁知道如何使这项工作? 什么样的指针应该传递给C函数? 回调实现应该如何重定向到调用对象的事件函数?
这恰好类似于我现在正在进行的工作。
这是一篇关于使用C ++类提供本地回调的博客文章:http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx
我不熟悉从C调用C ++成员函数,但是我已经为另一个用于回调的C ++类(类似于文章)完成了一个接口(抽象基类)类。 以下是我为以下方面提供桥梁的基本示例:
// Interface (abstract base) class providing the callback
class IProvider {
public:
virtual ~IProvider() {}
virtual void Callback() = 0;
};
// User class of the callback
class CUser {
IProvider * m_pProvider;
public:
CUser(IProvider * pProvider) {
m_pProvider = pProvider;
}
void DoSomething() {
m_pProvider->Callback();
}
};
// Implementation of the interface class
class CHelloWorldProvider : public IProvider {
void Callback() {
printf("Hello World!");
}
};
// Usage of the callback provider in a pure native setting
void PureNativeUsage() {
CHelloWorldProvider oProvider;
CUser oUser(&oProvider);
oUser.DoSomething();
}
现在为了使这个提供者的管理实现可用,我们必须创建一系列提供桥梁的类。
// Where gcroot is defined
#include <vcclr.h>
// Managed provider interface class
public interface class IManagedProvider {
void Callback();
};
// Native bridge class that can be passed to the user
class CProviderBridge : public IProvider {
// Give the managed class full access
friend ref class ManagedProviderBase;
// Store a reference to the managed object for callback redirects
gcroot<IManagedProvider ^> m_rManaged;
public:
void Callback(){
m_rManaged->Callback();
}
};
// Managed provider base class, this provides a managed base class for extending
public ref class ManagedProviderBase abstract : public IManagedProvider {
// Pointer to the native bridge object
CProviderBridge * m_pNative;
protected:
ManagedProviderBase() {
// Create the native bridge object and set the managed reference
m_pNative = new CProviderBridge();
m_pNative->m_rManaged = this;
}
public:
~ManagedProviderBase() {
delete m_pNative;
}
// Returns a pointer to the native provider object
IProvider * GetProvider() {
return m_pNative;
}
// Makes the deriving class implement the function
virtual void Callback() = 0;
};
// Pure managed provider implementation (this could also be declared in another library and/or in C#/VB.net)
public ref class ManagedHelloWorldProvider : public ManagedProviderBase {
public:
virtual void Callback() override {
Console::Write("Hello World");
}
};
// Usage of the managed provider from the native user
void MixedUsage() {
ManagedHelloWorldProvider ^ rManagedProvider = gcnew ManagedHelloWorldProvider;
CUser oUser(rManagedProvider->GetProvider());
oUser.DoSomething();
}
编辑:添加代码以显示不使用我使用的托管界面类示例。
这里是我的例子的修改版本,可以使用上面的CLibFunc
。 这是假设C函数如何执行回调是准确的。
此外,这可能会减少一点,这取决于您的回调类的参与程度以及您需要多少扩展的自由度。
// Where gcroot is defined
#include <vcclr.h>
// C callback signature
// Second parameter is meant to point to the calling C++ object
typedef int (__stdcall CLIBCALLBACK) (int param1, void *caller);
// C library function
void CLibFunc(CLIBCALLBACK *callback, void *caller) {
// Do some work
(*callback)(1234, caller);
// Do more work
}
// Managed caller interface class
public interface class IManagedCaller {
void EventFunction(int param1);
};
// C++ native bridge struct
struct CCallerBridge {
// Give the managed class full access
friend ref class ManagedCaller;
// Store a reference to the managed object for callback redirects
gcroot<IManagedCaller ^> m_rManaged;
public:
// Cast the caller to the native bridge and call managed event function
// Note: This must be __stdcall to prevent function call stack corruption
static int __stdcall CallBackImpl(int param1, void * caller) {
CCallerBridge * pCaller = (CCallerBridge *) caller;
pCaller->m_rManaged->EventFunction(param1);
return 0;
}
};
// C++/CLI caller class
public ref class ManagedCaller : public IManagedCaller {
// Pointer to the native bridge object
CCallerBridge * m_pNative;
public:
ManagedCaller() {
// Create the native bridge object and set the managed reference
m_pNative = new CCallerBridge();
m_pNative->m_rManaged = this;
}
~ManagedCaller() {
delete m_pNative;
}
// Calls the C library function
void CallerFunction() {
CLibFunc(CCallerBridge::CallBackImpl, m_pNative);
}
// Managed callback function
virtual void EventFunction(int param1) {
Console::WriteLine(param1);
}
};
// Usage
int main(array<System::String ^> ^args) {
ManagedCaller ^ oCaller = gcnew ManagedCaller();
oCaller->CallerFunction();
return 0;
}
链接地址: http://www.djcxy.com/p/4771.html