使用来自 iPhone ObjectiveC Apps 的 C/C++ 静态库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/376966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using C/C++ static libraries from iPhone ObjectiveC Apps
提问by Akusete
Is it possible to have a C static library API, which uses C++ internally and hide this from users of the library?
是否有可能有一个 C 静态库 API,它在内部使用 C++ 并向库的用户隐藏它?
I have writen a portable C++ library I wish to statically link to an iPhone application.
我编写了一个便携式 C++ 库,希望静态链接到 iPhone 应用程序。
I have created an Xcode project using the Max OS X 'static library' template, and copied the source across, as well as writing a C wapper (to deal with exceptions) using (extern "C").
我已经使用 Max OS X 的“静态库”模板创建了一个 Xcode 项目,并复制了源代码,并使用 (extern "C") 编写了一个 C wapper(以处理异常)。
I am trying to use the generated library (.a file) in another Cocoa iPhone application.
我正在尝试在另一个 Cocoa iPhone 应用程序中使用生成的库(.a 文件)。
Everything works well if the I use (.mm) extentions on the calling ObjectiveC file and (.cpp) on the implementation class in the library.
如果我在调用 ObjectiveC 文件上使用 (.mm) 扩展名,并在库中的实现类上使用 (.cpp) 扩展名,则一切正常。
But I get unresolved symbols on linking when I try and change the wrapper file to a (.c) extention, even though all the wrapper function files are only C functions.
但是当我尝试将包装器文件更改为 (.c) 扩展名时,我在链接时遇到了未解析的符号,即使所有包装器函数文件都只是 C 函数。
Just becuase C++ is used internally in a library, does it mean that externally it still must be treated as a C++ program. Is there not anyway to enforce this abstraction?
只是因为 C++ 在库内部使用,这是否意味着在外部它仍然必须被视为 C++ 程序。无论如何都没有强制执行这种抽象吗?
Edit:Thanks for the replies,
编辑:感谢您的回复,
I had been using extern "C", I was just unsure about what configurations where needed in the calling project. ie. if the calling projected would require to know if it used C++ or could be ignorant and think its a purely C library.
我一直在使用 extern "C",我只是不确定调用项目中需要哪些配置。IE。如果调用预计需要知道它是否使用 C++ 或者可能无知并认为它是一个纯粹的 C 库。
It would seem I cannot, and I must use (.mm) files on my ObjectiveC classes.
看起来我不能,我必须在我的 ObjectiveC 类中使用 (.mm) 文件。
回答by Jason Coco
It's too hard to do this in comments, so I'm just going to demonstrate for you quickly what the linking issues are that you're having. When Xcode encounters files, it uses build rules based on the suffix to decide which compiler to use. By default, gcc links the files to the standard C library, but does not link with the standard C++ library. Archive files (static libraries) have no linking resolution done at all. They are basically an archive of object files which need to be linked. Since you have no .mm or .cpp files in your project, g++ is never called and your files are never linked to the standard libraries. To correct this, just add the standard C++ libraries to your other linker flags in your Xcode project, or just simply add them to the pre-defined other flags option as -l (e.g., -lstdc++).
在评论中很难做到这一点,所以我将快速向您展示您遇到的链接问题是什么。当 Xcode 遇到文件时,它会根据后缀使用构建规则来决定使用哪个编译器。默认情况下,gcc 将文件链接到标准 C 库,但不链接到标准 C++ 库。存档文件(静态库)根本没有完成链接解析。它们基本上是需要链接的目标文件的存档。由于您的项目中没有 .mm 或 .cpp 文件,因此永远不会调用 g++ 并且您的文件永远不会链接到标准库。要纠正此问题,只需将标准 C++ 库添加到 Xcode 项目中的其他链接器标志,或者只是将它们作为 -l(例如,-lstdc++)添加到预定义的其他标志选项中。
Here is a quick demonstration:
这是一个快速演示:
stw.h:
stw.h:
#ifdef __cplusplus
extern "C"
#endif
void show_the_world(void);
stw.cpp:
stw.cpp:
#include <iostream>
#include "stw.h"
using namespace std;
extern "C" void show_the_world() {
cout << "Hello, world!\n";
}
Build the library:
构建库:
$ g++ -c stw.cpp -o stw.cpp -O0 -g
$ ar rcs stw.a stw.o
Using the library from a C application:
使用 C 应用程序中的库:
myapp.c:
myapp.c:
#include "stw.h"
int main() {
show_the_world();
return 0;
}
Building the C application:
构建 C 应用程序:
$ gcc -o myapp myapp.c stw.a -lstdc++ -g -O0
$ ./myapp
Hello, world!
$
If you try to compile without the -lstdc++ you will get all the unresolved issues because the C compiler has absolutely NO idea that it should link to the C++ runtime (and why would it, right!?!?) so you have to add this manually. The other option you have is to change the build rule for your project... instead of having Xcode use gcc to build .c and .m files, tell it to use g++ and your issues will be resolved.
如果您尝试在没有 -lstdc++ 的情况下进行编译,您将获得所有未解决的问题,因为 C 编译器完全不知道它应该链接到 C++ 运行时(为什么会这样,对吧!?!?)所以您必须添加它手动。您拥有的另一个选项是更改项目的构建规则......而不是让 Xcode 使用 gcc 来构建 .c 和 .m 文件,告诉它使用 g++ 并且您的问题将得到解决。
回答by coppro
You should declare the functions you want to be visible extern "C"
. Their signatures need to be C-compatible, but the contents do not (you may access C++ objects, for instance, but you cannot pass them directly; pointers are okay). The symbols will then be visible to any C-compatible environment.
你应该声明你想要可见的函数extern "C"
。它们的签名需要与 C 兼容,但内容不需要(例如,您可以访问 C++ 对象,但不能直接传递它们;指针是可以的)。然后这些符号对任何 C 兼容环境都是可见的。
EDIT: And compile it as a C++ source file, C doesn't have the notion of language linkage. There are a couple other gotchas with language linkage (like the fact that all extern "C"
functions with the same name are the same function, regardless of namespace).
编辑:并将其编译为 C++ 源文件,C 没有语言链接的概念。语言链接还有其他一些问题(例如,所有extern "C"
具有相同名称的函数都是相同的函数,而不管命名空间如何)。
EDIT2: In the header, you can check for the macro __cplusplus
, and use that to set for C++ and other languages, respectively (because C++ will require extern "C"
declarations, and other languages will probably complain about them).
EDIT2:在标题中,您可以检查宏__cplusplus
,并使用它分别为 C++ 和其他语言设置(因为 C++ 需要extern "C"
声明,而其他语言可能会抱怨它们)。
回答by Martin York
Basically when you compile the C functions with a C++ compiler it mangles the function names and uses the C++ ABI.
基本上,当您使用 C++ 编译器编译 C 函数时,它会破坏函数名称并使用 C++ ABI。
When you use the *.cpp or *.mm extension you are using the C++ compiler.
当您使用 *.cpp 或 *.mm 扩展名时,您使用的是 C++ 编译器。
What you want to do is force the compiler to generate C functions with un-mangles names and using the C ABI.
您想要做的是强制编译器生成具有 un-mangles 名称并使用 C ABI 的 C 函数。
You can do this by either:
您可以通过以下任一方式执行此操作:
- Compile with the C compiler.
- Compile with the C++ compiler but make sure that you prefix the function declarations with extern "C"
- 用 C 编译器编译。
- 使用 C++ 编译器进行编译,但请确保在函数声明前加上 extern "C"
A favorite way to set up the header file, so that the same file can be included from both C and C++ source files is:
设置头文件的一种常用方法是:可以从 C 和 C++ 源文件中包含相同的文件:
#ifndef HEADER_GUARD_1_H
#define HEADER_GUARD_1_H
#ifdef __cplusplus
extern "C" {
#endif
// Declare C function interface here.
int myFunc(int x,char*);
#ifdef __cplusplus
}
#endif
#endif
回答by Nareshkumar
thanks, for such good discussion.
谢谢,这么好的讨论。
what I did is:
我所做的是:
1) I created a static lib using cocaotouch static lib option. In that i have c/c++/obj-c all mix. however, my exports are only obj-c classes. Infact i used objc- to c to C++.
1)我使用 cocaotouch static lib 选项创建了一个静态库。因为我有 c/c++/obj-c 全部混合。但是,我的导出只是 obj-c 类。事实上,我使用 objc- 到 c 到 C++。
2) then I creatd iphone app in X-code proj. I added the otherlink flags my lib name ( -lxyz ) //my lib name is libxyz.a I added lib search path, header search path
2)然后我在 X-code proj 中创建了 iphone 应用程序。我添加了otherlink标志我的lib名称(-lxyz)//我的lib名称是libxyz.a我添加了lib搜索路径,标题搜索路径
3) then I compiled. I got errors. saying oeprator new, operator delete not found.
3)然后我编译。我有错误。说 operator new,找不到 operator delete。
3) then apart my appdelegate, view controller, I added dummy cpp(.h, .cpp)... atestdummy.h atestdummy.cpp
3)然后分开我的appdelegate,视图控制器,我添加了dummy cpp(.h, .cpp)... atestdummy.h atestdummy.cpp
4) then I build again...
4)然后我再次构建......
thats it worked.
就是这样。
So - I whatever suggestions they gave earlier workedfor me. basic reason, unless u r app sees a .cpp file .mm file with cpp code, linked will not use g++.
所以 - 我无论他们早先给出的任何建议都对我有用。基本原因,除非您的应用程序看到带有 cpp 代码的 .cpp 文件 .mm 文件,否则链接将不会使用 g++。
Thanks all. I have read the above and ssolved my problem.
谢谢大家。我已阅读以上内容并解决了我的问题。
u guys are good to share.
你们很高兴分享。