0

我想用 CEF4 构建一个测试应用程序。我已经成功地将 CEF4Delphi (github.com/salvadordf/CEF4Delphi) 组件安装到 C++ Builder。我想在 C++ Builder 中构建 JSExtension delphi 演示项目。

我正在尝试为成员设置一个函数,但每次都会出现相同的错误:

[bcc32 错误] Unit1.cpp(35): E2235 成员函数必须被调用或者它的地址被占用

我尝试了所有这些:

//This is my function, just a global function
void GlobalCEFApp_OnWebKitInitialized();

//For GlobalCEFApp object I want to assign my function to a member function OnWebKitInitialized of that object 
 GlobalCEFApp = new TCefApplication();


// I tried this:

GlobalCEFApp->OnWebKitInitialized = GlobalCEFApp_OnWebKitInitialized;
GlobalCEFApp->OnWebKitInitialized = &GlobalCEFApp_OnWebKitInitialized;
GlobalCEFApp->OnWebKitInitialized = (_di_TOnWebKitInitializedEvent*)GlobalCEFApp_OnWebKitInitialized;
GlobalCEFApp->OnWebKitInitialized = reinterpret_cast<TOnWebKitInitializedEvent &>(GlobalCEFApp_OnWebKitInitialized);

//But only this compiled, however it gives access violation at runtime
GlobalCEFApp->OnWebKitInitialized = ( _di_TOnWebKitInitializedEvent &)GlobalCEFApp_OnWebKitInitialized; 

如何正确地做到这一点?

我在 C++ Builder 中使用 CEF4Delphi (github.com/salvadordf/CEF4Delphi) 组件。在 delphi JSExtension 演示项目上,它运行良好,但我无法构建同一演示的 C++ 版本。C++使用delphi接口,不知道怎么正确使用。我需要将我的函数分配给 GlobalCEFApp->OnWebKitInitialized = 的成员函数?

4

2 回答 2

3

成员函数必须符合它们所在的类。

所以你需要使用&TheClassOfTheFunction::GlobalCEFApp_OnWebKitInitialized.

于 2019-03-22T13:00:02.280 回答
2

TCefApplication::OnWebKitInitialized事件被声明为使用该TOnWebKitInitializedEvent类型,该类型在uCEFInterfaces.pas单元中声明为:

TOnWebKitInitializedEvent = {$IFDEF DELPHI12_UP}reference to{$ENDIF} procedure() {$IFNDEF DELPHI12_UP}of object{$ENDIF};

CEFDELPHI12_UP在 Delphi/C++Builder 2009 及更高版本中定义。

您没有说您使用的是哪个版本的 C++Builder。

  • 如果您使用的是 C++Builder 2007 或更早版本,则该OnWebKitInitialized事件需要一个指向非静态类方法的指针。

  • 如果您使用的是 C++Builder 2009+,则该OnWebKitInitialized事件需要一个匿名方法

由于您提到您尝试使用_di_TOnWebKitInitializedEvent,它仅在TOnWebKitInitializedEvent是匿名方法类型时才存在,所以我必须假设您使用的是 C++Builder 2009+。

在 C++ 中,Delphi 风格的匿名方法需要特殊处理,Embarcadero 已经记录了这一点:

如何在 C++ 中处理 Delphi 匿名方法

您需要包装GlobalCEFApp_OnWebKitInitialized()才能将其用作匿名事件处理程序。为此,您有几个选择,具体取决于您使用的是经典的 Borland Win32/OSX 编译器还是较新的基于 Clang 的编译器之一。

  • 经典:您必须编写一个实现TOnWebKitInitializedEvent接口的仿函数:

    class TWebKitInitRef : public TCppInterfacedObject<TOnWebKitInitializedEvent>
    {
    public:
        INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);
        void __fastcall Invoke() { GlobalCEFApp_OnWebKitInitialized(); }
    };
    
    GlobalCEFApp->OnWebKitInitialized = _di_TOnWebKitInitializedEvent(new TWebKitInitRef());
    
  • Clang:您可以使用 C++ lambda:

    GlobalCEFApp->OnWebKitInitialized = [](){ GlobalCEFApp_OnWebKitInitialized(); };
    
于 2019-03-22T17:25:37.753 回答