c库的C/C++LI类包装器 – 回调

前端之家收集整理的这篇文章主要介绍了c库的C/C++LI类包装器 – 回调前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用C/C++LI包装C库. C库旨在从非托管C类中使用.这意味着库函数接受C对象指针,然后在回调中提供该指针.这使得回调代码能够将请求重定向调用C对象中的适当事件函数.

实际的功能非常复杂,所以我将问题空间简化为几个基本项:

  1. // C library function signature
  2. void CLibFunc(CLIBCALLBACK *callback,void *caller);
  3.  
  4. // C callback signature
  5. // Second parameter is meant to point to the calling C++ object
  6. typedef int (__stdcall CLIBCALLBACK) (int param1,void *caller);
  7.  
  8. // C callback implementation
  9. int CallBackImpl(int param1,void* caller)
  10. {
  11. // Need to call the ManagedCaller's EventFunction from here
  12. // ???
  13. }
  14.  
  15. // C++/CLI caller class
  16. public ref class ManagedCaller
  17. {
  18. public:
  19. void CallerFunction(void)
  20. {
  21. // Call the C library function
  22. // Need to pass some kind of this class pointer that refers to this object
  23. CLibFunc(CallBackImpl,????);
  24. }
  25.  
  26. void EventFunction(param1)
  27. {
  28. }
  29. }

现在需要从托管C类调用C库函数.在C/C++LI下,垃圾收集器在内存中移动对象,因此将一个简单的固定指针传递给该类不再起作用.我可以通过固定对象来解决问题,但不建议这样做,因为它会导致内存碎片.似乎另一种选择是使用auto_gcroot指针,但我对托管C相当新,我不知道如何使这项工作.

有谁知道如何使这项工作?什么样的指针应该传递给C函数?如何将回调实现重定向调用对象的事件函数

解决方法

这恰好与我正在进行的工作类似.

这是一篇关于使用C类提供本机回调的博客文章http://blogs.microsoft.co.il/blogs/alon/archive/2007/05/29/Native-Callback.aspx

我不熟悉从C调用C成员函数,但我已经为另一个C类做了一个接口(抽象基类)来进行回调(类似于文章).以下是我为以下内容提供桥梁的基本示例:

  1. // Interface (abstract base) class providing the callback
  2. class IProvider {
  3. public:
  4. virtual ~IProvider() {}
  5. virtual void Callback() = 0;
  6. };
  7.  
  8. // User class of the callback
  9. class CUser {
  10. IProvider * m_pProvider;
  11. public:
  12. CUser(IProvider * pProvider) {
  13. m_pProvider = pProvider;
  14. }
  15. void DoSomething() {
  16. m_pProvider->Callback();
  17. }
  18. };
  19.  
  20. // Implementation of the interface class
  21. class CHelloWorldProvider : public IProvider {
  22. void Callback() {
  23. printf("Hello World!");
  24. }
  25. };
  26.  
  27. // Usage of the callback provider in a pure native setting
  28. void PureNativeUsage() {
  29. CHelloWorldProvider oProvider;
  30. CUser oUser(&oProvider);
  31. oUser.DoSomething();
  32. }

现在,为了使其可用于提供者的托管实现,我们必须创建一系列提供桥接的类.

  1. // Where gcroot is defined
  2. #include <vcclr.h>
  3.  
  4. // Managed provider interface class
  5. public interface class IManagedProvider {
  6. void Callback();
  7. };
  8.  
  9. // Native bridge class that can be passed to the user
  10. class CProviderBridge : public IProvider {
  11. // Give the managed class full access
  12. friend ref class ManagedProviderBase;
  13.  
  14. // Store a reference to the managed object for callback redirects
  15. gcroot<IManagedProvider ^> m_rManaged;
  16.  
  17. public:
  18. void Callback(){
  19. m_rManaged->Callback();
  20. }
  21. };
  22.  
  23. // Managed provider base class,this provides a managed base class for extending
  24. public ref class ManagedProviderBase abstract : public IManagedProvider {
  25. // Pointer to the native bridge object
  26. CProviderBridge * m_pNative;
  27.  
  28. protected:
  29. ManagedProviderBase() {
  30. // Create the native bridge object and set the managed reference
  31. m_pNative = new CProviderBridge();
  32. m_pNative->m_rManaged = this;
  33. }
  34.  
  35. public:
  36. ~ManagedProviderBase() {
  37. delete m_pNative;
  38. }
  39.  
  40. // Returns a pointer to the native provider object
  41. IProvider * GetProvider() {
  42. return m_pNative;
  43. }
  44.  
  45. // Makes the deriving class implement the function
  46. virtual void Callback() = 0;
  47. };
  48.  
  49. // Pure managed provider implementation (this could also be declared in another library and/or in C#/VB.net)
  50. public ref class ManagedHelloWorldProvider : public ManagedProviderBase {
  51. public:
  52. virtual void Callback() override {
  53. Console::Write("Hello World");
  54. }
  55. };
  56.  
  57. // Usage of the managed provider from the native user
  58. void MixedUsage() {
  59. ManagedHelloWorldProvider ^ rManagedProvider = gcnew ManagedHelloWorldProvider;
  60. CUser oUser(rManagedProvider->GetProvider());
  61. oUser.DoSomething();
  62. }

编辑:添加代码显示我使用的托管接口类示例.

这是我的示例的修改版本,可以在上面的CLibFunc中使用.这假设C函数执行回调的方式是准确的.

此外,根据您的回调类的参与程度以及您需要多少扩展自由,这可能会稍微减少一些.

  1. // Where gcroot is defined
  2. #include <vcclr.h>
  3.  
  4. // C callback signature
  5. // Second parameter is meant to point to the calling C++ object
  6. typedef int (__stdcall CLIBCALLBACK) (int param1,void *caller);
  7.  
  8. // C library function
  9. void CLibFunc(CLIBCALLBACK *callback,void *caller) {
  10. // Do some work
  11. (*callback)(1234,caller);
  12. // Do more work
  13. }
  14.  
  15. // Managed caller interface class
  16. public interface class IManagedCaller {
  17. void EventFunction(int param1);
  18. };
  19.  
  20. // C++ native bridge struct
  21. struct CCallerBridge {
  22. // Give the managed class full access
  23. friend ref class ManagedCaller;
  24.  
  25. // Store a reference to the managed object for callback redirects
  26. gcroot<IManagedCaller ^> m_rManaged;
  27.  
  28. public:
  29. // Cast the caller to the native bridge and call managed event function
  30. // Note: This must be __stdcall to prevent function call stack corruption
  31. static int __stdcall CallBackImpl(int param1,void * caller) {
  32. CCallerBridge * pCaller = (CCallerBridge *) caller;
  33. pCaller->m_rManaged->EventFunction(param1);
  34. return 0;
  35. }
  36. };
  37.  
  38. // C++/CLI caller class
  39. public ref class ManagedCaller : public IManagedCaller {
  40. // Pointer to the native bridge object
  41. CCallerBridge * m_pNative;
  42.  
  43. public:
  44. ManagedCaller() {
  45. // Create the native bridge object and set the managed reference
  46. m_pNative = new CCallerBridge();
  47. m_pNative->m_rManaged = this;
  48. }
  49. ~ManagedCaller() {
  50. delete m_pNative;
  51. }
  52.  
  53. // Calls the C library function
  54. void CallerFunction() {
  55. CLibFunc(CCallerBridge::CallBackImpl,m_pNative);
  56. }
  57.  
  58. // Managed callback function
  59. virtual void EventFunction(int param1) {
  60. Console::WriteLine(param1);
  61. }
  62. };
  63.  
  64. // Usage
  65. int main(array<System::String ^> ^args) {
  66. ManagedCaller ^ oCaller = gcnew ManagedCaller();
  67. oCaller->CallerFunction();
  68. return 0;
  69. }

猜你在找的C&C++相关文章