views:

68

answers:

2

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/mingw32/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:
A: 

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.

Jack Kelly
Thanks, that makes a lot more sense, when I do that though - the problem is that it goes back to not finding the greet() symbol?
Beaks
You need `#ifdef __cplusplus` `extern "C"` `#endif` in the header so that the C++ compiler knows what symbol to expect.
Jack Kelly
A: 

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.

Jack Kelly