简体   繁体   English

使用iPhone ObjectiveC Apps中的C / C ++静态库

[英]Using C/C++ static libraries from iPhone ObjectiveC Apps

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. 因为C ++是在库内部使用的,它是否意味着在外部它仍然必须被视为C ++程序。 Is there not anyway to enforce this abstraction? 无论如何都没有强制执行这种抽象?

Edit: Thanks for the replies, 编辑:谢谢你的回复,

I had been using extern "C", I was just unsure about what configurations where needed in the calling project. 我一直在使用extern“C”,我只是不确定调用项目需要哪些配置。 ie. 即。 if the calling projected would require to know if it used C++ or could be ignorant and think its a purely C library. 如果调用的预测需要知道它是否使用C ++或者可能是无知的并且认为它是纯粹的C库。

It would seem I cannot, and I must use (.mm) files on my ObjectiveC classes. 看起来我不能,我必须在ObjectiveC类上使用(.mm)文件。

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. 当Xcode遇到文件时,它使用基于后缀的构建规则来决定使用哪个编译器。 By default, gcc links the files to the standard C library, but does not link with the standard C++ library. 默认情况下,gcc将文件链接到标准C库,但不链接到标准C ++库。 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. 由于项目中没有.mm或.cpp文件,因此永远不会调用g ++,并且您的文件永远不会链接到标准库。 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 (eg, -lstdc++). 要解决此问题,只需将标准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. 如果你尝试在没有-lstdc ++的情况下进行编译,你将得到所有未解决的问题,因为C编译器绝对不知道它应该链接到C ++运行时(为什么会这样,对吧!?!?)所以你必须添加这个手动。 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. 您拥有的另一个选择是更改项目的构建规则...而不是让Xcode使用gcc来构建.c和.m文件,告诉它使用g ++,您的问题将得到解决。

You should declare the functions you want to be visible extern "C" . 您应该声明要显示为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). 他们的签名需要是C兼容的,但内容不是(例如,你可以访问C ++对象,但你不能直接传递它们;指针是可以的)。 The symbols will then be visible to any C-compatible environment. 然后,符号将对任何C兼容环境可见。

EDIT: And compile it as a C++ source file, C doesn't have the notion of language linkage. 编辑:并将其编译为C ++源文件,C没有语言链接的概念。 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). 还有一些其他问题与语言链接(例如,所有具有相同名称的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"声明,而其他语言可能会抱怨它们)。

thanks, for such good discussion. 谢谢,这样的好讨论。

what I did is: 我做的是:

1) I created a static lib using cocaotouch static lib option. 1)我使用cocaotouch static lib选项创建了一个静态库。 In that i have c/c++/obj-c all mix. 在那我有c / c ++ / obj-c所有混合。 however, my exports are only obj-c classes. 但是,我的出口只是obj-c类。 Infact i used objc- to c to C++. 事实上我使用objc-to c到C ++。

2) then I creatd iphone app in X-code proj. 2)然后我在X-code proj中创建了iphone应用程序。 I added the otherlink flags my lib name ( -lxyz ) //my lib name is libxyz.a I added lib search path, header search path 我添加了其他链接标志我的lib名称(-lxyz)//我的lib名称是libxyz.a我添加了lib搜索路径,标题搜索路径

3) then I compiled. 3)然后我编译。 I got errors. 我有错误。 saying oeprator new, operator delete not found. 说oeprator new,找不到operator delete。

3) then apart my appdelegate, view controller, I added dummy cpp(.h, .cpp)... atestdummy.h atestdummy.cpp 3)然后分开我的appdelegate,查看控制器,我添加了虚拟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 ur 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. 你们很高兴分享。

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函数并使用C ABI。

You can do this by either: 你可以这样做:

  • Compile with the C compiler. 用C编译器编译。
  • Compile with the C++ compiler but make sure that you prefix the function declarations with extern "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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM