Mix C++ and Objective-C code using CMake and get C++ executable.

huangapple go评论72阅读模式
英文:

Mix C++ and Objective-C code using CMake and get C++ executable

问题

可以使用Objective-C和Cocoa库构建一个独立的库,并为其创建一个公共接口,以便在C++项目中使用。这是完全可能的,而且你的项目已经朝着正确的方向迈出了一些重要步骤。

在你的项目中,你有一个名为WindowBuilderObjCLib的Objective-C++库,该库使用了Cocoa库,并且已经为其创建了一个公共接口src/Draw/WindowBuilder/WindowBuilder.h。这个库的公共接口允许你从C++代码中调用Objective-C++的功能。

然而,要解决你遇到的编译错误,你需要确保在C++代码中正确包含Objective-C++库的头文件,并正确链接Objective-C++库。在你的main.cpp文件中,确保你正确包含了库的头文件,例如:

#include <Draw/WindowBuilder/WindowBuilder.h>

然后,在CMakeLists.txt中,确保你的Engine目标链接到WindowBuilderObjCLib

target_link_libraries(Engine PRIVATE
    WindowBuilderObjCLib
    DrawLib
    UtilsLib
    OpenGL::GL
    ${FOUNDATION_FRAMEWORK}
)

这样做后,你的C++代码应该能够正确调用Objective-C++库中的函数,并且不再出现编译错误。

总之,是可以构建一个包含Objective-C代码的独立库,并在C++项目中使用的。只需确保正确设置包含路径和链接库,以便在C++代码中使用Objective-C部分。

英文:

The Idea

I'm trying to implement a game engine in C++.

I'm using macOS for development (arm-64 architecture). I want to create a window using Foundation framework.

CMakeLists.txt utilizes C++ and Objective-C languages, and I want to build a library containing only Objective-C code and then use this library in my C++ code (probably including the header). The end result should be a C++ executable.

The Project Structure

[src]
    ├── [Draw]
        ├── Window.cpp
        ├── Window.h
        └── [WindowBuilder]
            ├── WindowBuilder.cpp
            ├── WindowBuilder.h
            └── [macOS]
                ├── WindowBuilderObjC.h
                └── WindowBuilderObjC.mm
    ├── [Utils]
        └── Size.h
    ├── main.cpp
└── CMakeLists.txt

The Source Code

src/Draw/Window.h

#include &lt;iostream&gt;

#include &lt;Utils/Size.h&gt;
#include &quot;WindowBuilder/WindowBuilder.h&quot;

#pragma once

namespace Draw
{

    class Window
    {
    private:
        bool _isPresented;
        Utils::Size _size = Utils::Size(0, 0);

        WindowBuilder::WindowBuilder *_builder;

        Window();
        ~Window() = default;

    public:
        // Public static member function to access the singleton instance
        static Window &amp;Instance()
        {
            // Guaranteed to be initialized once
            static Window instance;
            return instance;
        }

        // Delete the copy constructor and assignment operator
        Window(const Window &amp;) = delete;
        Window &amp;operator=(const Window &amp;) = delete;

        void SetSize(Utils::Size size);
        void DrawWindow();
    };
}

src/Draw/Window.cpp

#include &quot;Window.h&quot;

namespace Draw
{
    Window::Window()
    {
        _builder = &amp;WindowBuilder::WindowBuilder::Instance();
    }

    void Window::SetSize(Utils::Size size)
    {
        _size = size;
    }

    void Window::DrawWindow()
    {
        std::cout &lt;&lt; &quot;Draw window with size: [&quot; &lt;&lt; _size.GetWidth() &lt;&lt; &quot;:&quot; &lt;&lt; _size.GetHeight() &lt;&lt; &quot;]&quot; &lt;&lt; std::endl;

        _builder-&gt;BuildWindow(_size);
    }
}

src/WindowBuilder/WindowBuilder.h

// General
#include &lt;iostream&gt;

// Internal
#include &lt;Utils/Size.h&gt;
#include &lt;Draw/WindowBuilder/macOS/WindowBuilderObjC.h&gt;

#pragma once

namespace WindowBuilder
{
    class WindowBuilder
    {
    private:
        bool _isPresented;

        WindowBuilder() = default;
        ~WindowBuilder() = default;

    public:
        static WindowBuilder &amp;Instance()
        {
            // Guaranteed to be initialized once
            static WindowBuilder instance;
            return instance;
        }

        // Delete the copy constructor and assignment operator
        WindowBuilder(const WindowBuilder &amp;) = delete;
        WindowBuilder &amp;operator=(const WindowBuilder &amp;) = delete;

        void BuildWindow(Utils::Size size);
    };
}

src/WindowBuilder/WindowBuilder.cpp

#include &quot;WindowBuilder.h&quot;

namespace WindowBuilder
{
    void WindowBuilder::BuildWindow(Utils::Size size)
    {
        buildWindowWithSize(size);
    }
}

src/Draw/WindowBuilder/macOS/WindowBuilderObjC.h

#import &lt;Cocoa/Cocoa.h&gt;

#import &quot;Utils/Size.h&quot;

@interface WindowBuilderObjC : NSObject

- (void)buildWindowWithSize:(Utils::Size)size;

@end

@interface WindowDelegate : NSObject &lt;NSWindowDelegate&gt;
@end

@implementation WindowDelegate

- (BOOL)windowShouldClose:(id)sender
{
    [NSApp terminate:nil];
    return YES;
}

@end

src/Draw/WindowBuilder/macOS/WindowBuilderObjC.mm

#import &quot;WindowBuilderObjC.h&quot;

@implementation WindowBuilderObjC

- (void)buildWindowWithSize:(Utils::Size)size
{
    @autoreleasepool 
    {
        [NSApplication sharedApplication];
        
        NSRect frame = NSMakeRect(0, 0, 800, 600);
        NSUInteger style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
        NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:style backing:NSBackingStoreBuffered defer:NO];
        [window setTitle:@&quot;My Window&quot;];
        [window center];
        
        WindowDelegate *delegate = [[WindowDelegate alloc] init];
        [window setDelegate:delegate];
        
        [window makeKeyAndOrderFront:nil];
        
        [NSApp run];
    }
}

@end

src/main.cpp

#include &lt;iostream&gt;

#include &lt;Draw/Window.h&gt;

#include &lt;Utils/Size.h&gt;

int main()
{
    std::cout &lt;&lt; &quot;Hello World&quot; &lt;&lt; std::endl;

    Utils::Size size(600, 800);

    auto &amp;window = Draw::Window::Instance();
    window.SetSize(size);

    window.DrawWindow();
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(GameEngine LANGUAGES CXX OBJC OBJCXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# enable_language(OBJC)
# enable_language(OBJCXX)

add_executable(Engine src/main.cpp)

add_library(UtilsLib SHARED
    src/Utils/Size.h
)

set_target_properties(UtilsLib PROPERTIES LINKER_LANGUAGE CXX)

add_library(WindowBuilderObjCLib SHARED
    src/Draw/WindowBuilder/macOS/WindowBuilderObjC.h
        src/Draw/WindowBuilder/macOS/WindowBuilderObjC.mm
)

target_include_directories(WindowBuilderObjCLib
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src/Draw/WindowBuilder/macOS
)

target_link_libraries(WindowBuilderObjCLib
    PRIVATE &quot;-framework Cocoa&quot;
    PRIVATE &quot;-framework Foundation&quot;
    PRIVATE &quot;-framework AppKit&quot;
)

# Set the language for the library to Objective-C++
set_target_properties(WindowBuilderObjCLib PROPERTIES
    LINKER_LANGUAGE &quot;OBJCXX&quot;
    XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES
    XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES YES
    XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_WEAK YES
)

add_library(DrawLib STATIC
        src/Draw/Window.h
        src/Draw/Window.cpp
)

target_sources(DrawLib
  PRIVATE
    src/Draw/WindowBuilder/WindowBuilder.h
    src/Draw/WindowBuilder/WindowBuilder.cpp
)

target_sources(DrawLib
  PUBLIC
    src/Draw/Window.h
    src/Draw/Window.cpp
)

set_target_properties(DrawLib PROPERTIES LINKER_LANGUAGE CXX)

find_library(FOUNDATION_FRAMEWORK Foundation)

# Link against required frameworks and libraries
target_link_libraries(DrawLib
    PRIVATE ${FOUNDATION_FRAMEWORK}
    &quot;-framework AppKit&quot;
    &quot;-framework CoreGraphics&quot;
    &quot;-lobjc&quot;
)

find_package(OpenGL REQUIRED COMPONENTS OpenGL)

include_directories(${CMAKE_SOURCE_DIR}/src)

add_subdirectory(src/Draw/WindowBuilder/macOS)

# Link the DrawLib and UtilsLib targets to the Engine target
target_link_libraries(Engine PRIVATE
    WindowBuilderObjCLib
    DrawLib
    UtilsLib
    OpenGL::GL
    ${FOUNDATION_FRAMEWORK}
)

The Error

Seems like when I include Window.h into main.cpp, the compiler looks for symbols in Cocoa/Cocoa.h file and finds Objective-C symbols instead of C++.

The error is following:

[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/Window.cpp:1:
[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/Window.h:4:
[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/WindowBuilder/WindowBuilder.h:6:
[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/WindowBuilder/macOS/WindowBuilderObjC.h:1:
[build] In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h:12:
[build] In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:8:
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:601:1: error: expected unqualified-id
[build] @class NSString, Protocol;
[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/WindowBuilder/WindowBuilder.cpp:1:
[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/WindowBuilder/WindowBuilder.h:6:
[build] ^
[build] In file included from /Users/user/MySource/GameEngine_Vulkan/src/Draw/WindowBuilder/macOS/WindowBuilderObjC.h:1:
[build] In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Cocoa.framework/Headers/Cocoa.h:12:
[build] In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:8:
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:601:1: error: expected unqualified-id
[build] @class NSString, Protocol;
[build] ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:603:9: error: unknown type name &#39;NSString&#39;
[build] typedef NSString * NSExceptionName NS_TYPED_EXTENSIBLE_ENUM;
[build]         ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:603:9: error: unknown type name &#39;NSString&#39;
[build] typedef NSString * NSExceptionName NS_TYPED_EXTENSIBLE_ENUM;
[build]         ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:604:9: error: unknown type name &#39;NSString&#39;
[build] typedef NSString * NSRunLoopMode NS_TYPED_EXTENSIBLE_ENUM;
[build]         ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:604:9: error: unknown type name &#39;NSString&#39;
[build] typedef NSString * NSRunLoopMode NS_TYPED_EXTENSIBLE_ENUM;
[build]         ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:606:19: error: unknown type name &#39;NSString&#39;
[build] FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);
[build]                   ^
[build] /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:606:19: error: unknown type name &#39;NSString&#39;
[build] FOUNDATION_EXPORT NSString *NSStringFromSelector(SEL aSelector);
[build]                   ^

...

The Question

Can I build a standalone library using Objective-C with Cocoa lib included (probably) and that it will have a public interface, so that I can use it in C++ project?

答案1

得分: 0

以下是翻译好的部分:

1. 在Objective-C中编写代码,提供所需的功能(在我的情况下,创建macOS窗口):

WindowBuilderObjC.h

#ifndef WindowBuilderObjC_h
#define WindowBuilderObjC_h

#import <Cocoa/Cocoa.h>

@interface WindowBuilderObjC : NSObject

- (void)buildWindowWithWidth:(int)width height:(int)height;

@end

@interface WindowDelegate : NSObject <NSWindowDelegate>
@end

#endif /* WindowBuilderObjC_h */

WindowBuilderObjC.mm

#import "WindowBuilderObjC.h"

@implementation WindowBuilderObjC

- (void)buildWindowWithWidth:(int)width height:(int)height
{
    @autoreleasepool
    {
        [NSApplication sharedApplication];
        [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];

        NSRect frame = NSMakeRect(0, 0, 800, 600);
        NSUInteger style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
        NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:style backing:NSBackingStoreBuffered defer:NO];
        [window setTitle:@"My Window"];
        [window center];

        WindowDelegate *delegate = [[WindowDelegate alloc] init];
        [window setDelegate:delegate];

        [window makeKeyWindow];
        [window orderFrontRegardless];

        [NSApp run];
    }
}

@end

@implementation WindowDelegate

- (BOOL)windowShouldClose:(id)sender
{
    [NSApp terminate:nil];
    return YES;
}

@end

2. 创建一个文件(仍然是Objective-C),使用关键字 extern "C" 来包含C++头文件(以便在C++代码中使用):

WindowBuilderObjCWrapper.mm

extern "C"
{
#import "WindowBuilderObjC.h"
}

extern "C" WindowBuilderObjC *createWindowBuilder()
{
    WindowBuilderObjC* builder = [[WindowBuilderObjC alloc] init];

    return builder;
}

extern "C" void deleteWindowBuilder(WindowBuilderObjC *builder)
{
    [builder dealloc];
}

extern "C" void buildWindow(WindowBuilderObjC *builder, int* width, int* height)
{
    [builder buildWindowWithWidth:*width height:*height];
}

3. 修改CMakeLists.txt以从Objective-C文件创建一个模块库:

CMakeLists.txt

add_library(WindowBuilderObjCLib MODULE
    src/Utils/WindowBuilder/macOS/Objective-C/WindowBuilderObjCWrapper.mm
)

target_sources(WindowBuilderObjCLib
  PRIVATE
    src/Utils/WindowBuilder/macOS/Objective-C/WindowBuilderObjC.h
    src/Utils/WindowBuilder/macOS/Objective-C/WindowBuilderObjC.mm
)

target_link_libraries(WindowBuilderObjCLib
    PRIVATE "-framework Cocoa"
    PRIVATE "-framework Foundation"
    PRIVATE "-framework AppKit"
)

# 设置库的语言为Objective-C++
set_target_properties(WindowBuilderObjCLib PROPERTIES
    LINKER_LANGUAGE "CXX"
    XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES
    XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES YES
    XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_WEAK YES
)

4. 在C++中按照以下步骤操作:

4.1. 使用 dlfcn.h 库打开库:

// 打开库
lib_handle = dlopen("./build/libWindowBuilderObjCLib.so", RTLD_LOCAL);
if (!lib_handle)
{
    exit(EXIT_FAILURE);
}

4.2.(可选)使用 boost 库来检查打开的库是否包含所需的函数签名:

// 引入Boost库用于库信息
#include <boost/dll/library_info.hpp>

static void PrintSymbols(std::string libPath)
{
    // 类`library_info`可以从库中提取信息
    boost::dll::library_info inf(libPath);

    // 获取导出符号
    std::vector<std::string> exports = inf.symbols();

    // 打印符号
    for (std::size_t j = 0; j < exports.size(); ++j)
    {
        std::cout << exports[j] << std::endl;
    }
}

4.3.(可选)在C++类中创建将使用库函数的方法签名(也可以根据签名构建自己的实现):

// Objective-C包装器的签名
typedef void (*buildWindowObjC)(void *builder, int *width, int *height);
typedef void *(*createWindowBuilderObjC)();
typedef void *(*deleteWindowBuilderObjC)(void *builder);

// Objective-C处理程序
createWindowBuilderObjC createWindowBuilderObjCHandler;
buildWindowObjC buildWindowObjCHandler;
deleteWindowBuilderObjC deleteWindowBuilderObjCHandler;

// Objective-C窗口构建器实例
void *windowBuilderObjC;

4.4. 从库中获取函数并将其转换为适当的签名:

// 加载函数
createWindowBuilderObjCHandler = reinterpret_cast<createWindowBuilderObjC>(dlsym(lib_handle, "createWindowBuilder"));
if (!createWindowBuilderObjCHandler)
{
    exit(EXIT_FAILURE);
}

buildWindowObjCHandler = reinterpret_cast<buildWindowObjC>(dlsym(lib_handle, "buildWindow"));
if (!buildWindowObjCHandler)
{
    exit(EXIT_FAILURE);
}

deleteWindowBuilderObjCHandler = reinterpret_cast<deleteWindowBuilderObjC>(dlsym(lib_handle, "deleteWindowBuilder"));
if (!deleteWindowBuilderObjCHandler)
{
    exit(EXIT_FAILURE);
}

4.5. 使用Objective-C函数(通过C++头文件)从导入的库中调用:

windowBuilderObjC = createWindowBuilderObjCHandler();

int width = size.GetWidth();
int height = size.GetHeight();
buildWindowObjCHandler(windowBuilderObjC, &width, &height);

// ...

deleteWindowBuilderObjCHandler(windowBuilderObjC);

// ...

以上是你提供的代码的翻译。

英文:

So for anyone who's looking for such kind of implementation to be used:

1. Write code in Objective-C that provides a functionality you want (in my case, creating a window in macOS):

WindowBuilderObjC.h

#ifndef WindowBuilderObjC_h
#define WindowBuilderObjC_h

#import &lt;Cocoa/Cocoa.h&gt;

@interface WindowBuilderObjC : NSObject

- (void)buildWindowWithWidth:(int)width height:(int)height;

@end

@interface WindowDelegate : NSObject &lt;NSWindowDelegate&gt;
@end

#endif /* WindowBuilderObjC_h */

WindowBuilderObjC.mm

#import &quot;WindowBuilderObjC.h&quot;

@implementation WindowBuilderObjC

- (void)buildWindowWithWidth:(int)width height:(int)height
{
    @autoreleasepool 
    {
        [NSApplication sharedApplication];
        [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];

        NSRect frame = NSMakeRect(0, 0, 800, 600);
        NSUInteger style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
        NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:style backing:NSBackingStoreBuffered defer:NO];
        [window setTitle:@&quot;My Window&quot;];
        [window center];
        
        WindowDelegate *delegate = [[WindowDelegate alloc] init];
        [window setDelegate:delegate];
        
        [window makeKeyWindow];
        [window orderFrontRegardless];

        [NSApp run];
    }
}

@end

@implementation WindowDelegate

- (BOOL)windowShouldClose:(id)sender
{
    [NSApp terminate:nil];
    return YES;
}

@end

2. Create a file (still in Objective-C) with C++ headers using keyword extern "C" (so they can be used in C++ code):

WindowBuilderObjCWrapper.mm

extern &quot;C&quot;
{
#import &quot;WindowBuilderObjC.h&quot;
}

extern &quot;C&quot; WindowBuilderObjC *createWindowBuilder()
{
    WindowBuilderObjC* builder = [[WindowBuilderObjC alloc] init];

    return builder;
}

extern &quot;C&quot; void deleteWindowBuilder(WindowBuilderObjC *builder)
{
    [builder dealloc];
}

extern &quot;C&quot; void buildWindow(WindowBuilderObjC *builder, int* width, int* height)
{    
    [builder buildWindowWithWidth:*width height:*height];
}

3. Modify CMakeLists.txt to create a module library from your Objective-C files:

CMakeLists.txt

add_library(WindowBuilderObjCLib MODULE
    src/Utils/WindowBuilder/macOS/Objective-C/WindowBuilderObjCWrapper.mm
)

target_sources(WindowBuilderObjCLib
  PRIVATE
    src/Utils/WindowBuilder/macOS/Objective-C/WindowBuilderObjC.h
    src/Utils/WindowBuilder/macOS/Objective-C/WindowBuilderObjC.mm
)

target_link_libraries(WindowBuilderObjCLib
    PRIVATE &quot;-framework Cocoa&quot;
    PRIVATE &quot;-framework Foundation&quot;
    PRIVATE &quot;-framework AppKit&quot;
)

# Set the language for the library to Objective-C++
set_target_properties(WindowBuilderObjCLib PROPERTIES
    LINKER_LANGUAGE &quot;CXX&quot;
    XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES
    XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES YES
    XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_WEAK YES
)

4. In C++ follow these steps:

4.1. Open the library using dlfcn.h lib:

// Open the library.
lib_handle = dlopen(&quot;./build/libWindowBuilderObjCLib.so&quot;, RTLD_LOCAL);
if (!lib_handle)
{
    exit(EXIT_FAILURE);
}

4.2. (Optional) Use boost lib to check if the opened library contains the required function signatures:

// Boost for lib info
#include &lt;boost/dll/library_info.hpp&gt;

static void PrintSymbols(std::string libPath)
{
    // Class `library_info` can extract information from a library
    boost::dll::library_info inf(libPath);

    // Getting exported symbols
    std::vector&lt;std::string&gt; exports = inf.symbols();

    // Printing symbols
    for (std::size_t j = 0; j &lt; exports.size(); ++j)
    {
        std::cout &lt;&lt; exports[j] &lt;&lt; std::endl;
    }
}

4.3. (Optional) Create method signatures in the C++ class that is going to use the library's functions (you can also build up your own implementation based on the signatures):

// Objective-C wrapper signatures
typedef void (*buildWindowObjC)(void *builder, int *width, int *height);
typedef void *(*createWindowBuilderObjC)();
typedef void *(*deleteWindowBuilderObjC)(void *builder);

// Objective-C handlers
createWindowBuilderObjC createWindowBuilderObjCHandler;
buildWindowObjC buildWindowObjCHandler;
deleteWindowBuilderObjC deleteWindowBuilderObjCHandler;

// Objective-C Window Builder Instance
void *windowBuilderObjC;

4.4. Get functions from the library and cast it to the suitable signature:

// Load functions
createWindowBuilderObjCHandler = reinterpret_cast&lt;createWindowBuilderObjC&gt;(dlsym(lib_handle, &quot;createWindowBuilder&quot;));
if (!createWindowBuilderObjCHandler)
{
    exit(EXIT_FAILURE);
}

buildWindowObjCHandler = reinterpret_cast&lt;buildWindowObjC&gt;(dlsym(lib_handle, &quot;buildWindow&quot;));
if (!buildWindowObjCHandler)
{
    exit(EXIT_FAILURE);
}

deleteWindowBuilderObjCHandler = reinterpret_cast&lt;deleteWindowBuilderObjC&gt;(dlsym(lib_handle, &quot;deleteWindowBuilder&quot;));
if (!deleteWindowBuilderObjCHandler)
{
    exit(EXIT_FAILURE);
}

4.5. Use the Objective-C functions (via C++ headers) from the imported library:

windowBuilderObjC = createWindowBuilderObjCHandler();

int width = size.GetWidth();
int height = size.GetHeight();
buildWindowObjCHandler(windowBuilderObjC, &amp;width, &amp;height);

// ...

deleteWindowBuilderObjCHandler(windowBuilderObjC);

// ...

Thats it. Hope it can be useful for someone.

huangapple
  • 本文由 发表于 2023年6月16日 07:26:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486081.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定