Mixing C++ and Objective-C (Suspected Automake problem)
So, I've been working for some time on connecting hashing out a trivial application, comprising C++ and Objective-C, to prove some concepts and try and learn something.
Here's where I'm at now, my command (being run, and re-run on changes) is
$ autoreconf -vis && make clean && ./configure && make && ./src/greetings
Note, that I'm hoping that it'll run when I'm done, here's a brief file list:
$ find . | ack '\.(?:cpp|mm|h)$' ./src/darwin/greet.cpp ./src/darwin/greeting.h ./src/darwin/greeting.mm ./src/greet.h ./src/main.cpp ./src/mingw32/greet.cpp ./src/m开发者_开发百科ingw32/greet.h
The files in full, can all be found in this Gist at Github.
Rather than being a problem specifically with mixing the languages ( I don't even make it that far) - I appear to stumble at the compiler not recognising that this is Objective-C
(or ObjecC++
) - for that reason, my autoconf files are in this gist.
With the complete error output here, also in a Gist.
Here's a sample:
In file included from /usr/include/c++/4.2.1/iosfwd:48, from /usr/include/c++/4.2.1/ios:43, from /usr/include/c++/4.2.1/ostream:45, from /usr/include/c++/4.2.1/iostream:45, from darwin/greet.cpp:10: /usr/include/c++/4.2.1/bits/stringfwd.h:48: error: template with C linkage /usr/include/c++/4.2.1/bits/stringfwd.h:51: error: template with C linkage /usr/include/c++/4.2.1/bits/stringfwd.h:54: error: template with C linkage /usr/include/c++/4.2.1/bits/stringfwd.h:58: error: template specialization with C linkage /usr/include/c++/4.2.1/bits/stringfwd.h:63: error: template specialization with C linkage In file included from /usr/include/c++/4.2.1/iosfwd:49, from /usr/include/c++/4.2.1/ios:43, from /usr/include/c++/4.2.1/ostream:45, from /usr/include/c++/4.2.1/iostream:45, from darwin/greet.cpp:10:
From playing around with the zip file, here is what I recommend:
Use a C-only interface on the language boundary. This will avoid automake's non-existent Objective-C++ support. Use the
#ifdef __cplusplus
extern "C"
#endif
trick on your headers to ensure that the C++ compiler is going to generate C functions and the Objective-C compiler can handle the headers. This will make it possible for the Objective-C code to call your interface.
Set up your source tree as you have before: common code in src/
, OS-specific code in src/darwin
, src/msdos
(:P), src/win32
and so on. List all sources in EXTRA_foo_SOURCES
in Makefile.am
.
In configure.ac
, test which platform you are compiling for and use AM_CONDITIONAL
to set flags that Makefile.am
can read (you've done this correctly already).
In Makefile.am
, use the conditionals to include the correct additional sources:
if OS_DARWIN
foo_SOURCES += darwin/foo.m darwin/bar.h darwin/baz.m
foo_LDFLAGS = -Wl,-framework,Foundation
endif
Note that because of how the linker is chosen, a C++ link will be attempted. Additional linker flags to make the Objective-C code link will need to be in foo_LDFLAGS
.
What had happened in your case was the following: In greet.h
, you did not declare void greet();
as extern "C"
. This meant that when main.cpp
was compiled, it expected a void greet()
that had C++ linkage (in my case, the symbol was greet
). darwin/greet.cpp
was compiled and had void greet()
declared as extern "C"
, so it produced a C version (with the symbol _greet
). Linking then failed because the linker expected a greet
symbol but nothing provided that.
Your "template with C linkage" problem is due to the #include <iostream>
inside the extern "C"
block. Try something like this:
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
/* In a #ifdef __cplusplus block, if you want. */
extern "C"
void greet() {
/* ... */
}
This will make greet()
have C linkage, without the headers getting misinterpreted.
精彩评论