我正在尝试在OSX上的GTK +上做一些工作,但遇到了一些麻烦,因为老实说,我对Objective-C并不那么熟悉。我有足够的编程经验,可以快速掌握基本语法,并且可以查找文档中需要的内容。但是我遇到的问题与链接库和将类暴露给要链接的程序有关。
GTK +是一个C库,但是OSX后端包括几个Objective-C类。它们不公开为公共API,仅在内部使用;但是对于我正在做的事情,我想尝试公开公开这些类。
供参考,这是类之一:
https://github.com/GNOME/gtk/blob/gtk-2-24/gdk/quartz/GdkQuartzWindow.hhttps://github.com/GNOME/gtk/blob/gtk-2-24/gdk/quartz/GdkQuartzWindow.c
我已经更改了构建系统,以便安装头文件。我有另一个源文件(在gtk +构建系统之外),其功能类似于:
GdkQuartzWindow *win = [[GdkQuartzWindow alloc] /* other messages... */ ];
当我尝试编译时,出现链接器错误:
Undefined symbols for architecture i386:
".objc_class_name_GdkQuartzWindow", referenced from:
pointer-to-literal-objc-class-name in main-a8d029.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我对Objective-C编译器/链接器的工作方式不太熟悉,并且在理解如何(或如果可以)解决此问题时遇到麻烦。
[当我运行nm libgdk-quartz-2.0.dylib | grep GdkQuartzWindow
时,我在该课程上看到很多消息:
00057120 t -[GdkQuartzWindow beginManualMove] 000575c0 t -[GdkQuartzWindow beginManualResize] 00056c50 t -[GdkQuartzWindow canBecomeKeyWindow] ... (many more) ... 000b2030 s .objc_class_name_GdkQuartzWindow
在该列表的底部,您看到链接器在抱怨的东西不存在。但是,如果我使用
nm -g
而不是nm
,则不会显示任何内容,因此某些内容无法正确导出。
对于普通的C符号,构建过程将构建一个包含]的别名文件>
Apple's docs给我的印象是,当我的目标是i386(当前是它)时,这应该不是问题。他们说:
在32位OS X项目中,这些可见性控件仅适用于代码的C或C ++子集。它们不适用于Objective-C类和方法。 Objective-C类和消息名称是由Objective-C运行时而不是链接程序绑定的,因此可见性的概念不适用于它们。没有机制可以从动态库的客户端隐藏动态库中定义的Objective-C类或方法。
但是,我收到一条错误消息,说我有未定义的符号,因此我的错误似乎与此矛盾。如果我更改此行以便改为分配
NSWindow
,则一切正常。因此它可以正确导入AppKit内容。似乎在尝试公开类及其方法时做错了。有人有机会向我指出正确的方向吗?
我正在尝试在OSX上的GTK +上做一些工作,但遇到了一些麻烦,因为老实说,我对Objective-C并不那么熟悉。我有足够的编程经验,因此很快就起床了...
作为一种临时的解决方法,您可以通过将类名作为参数传递给NSClassFromString
的调用来替换对代码中类符号的引用。例如:
GdkQuartzWindow *win = [[NSClassFromString(@"GdkQuartzWindow") alloc] /* other messages... */ ];
我建议您在链接到GTK +时确保使用-ObjC
标志。您可以将其添加到目标“构建设置”中的“其他链接器标志”下。如果这不起作用,则可以尝试添加-all_load
链接器标志。
我在混合C / C ++代码和ObjectiveC包装器的库中遇到类似的问题。在这种情况下,我正在使用-fvisibility=hidden
gcc / clang标志编译整个库。这具有隐藏所有ObjectiveC类符号的直接效果。一种不太知名/不常用的技术是用可见性属性来装饰类。这广泛用于C / C ++,但也适用于ObjectiveC声明的类型。让我们首先创建一个OBJC_MYLIBRARY_API
宏,该宏将使libdefs.h
文件中的编译单元具有可见性: