Thread overview
extern(C++) linker errors
Apr 22, 2015
bitwise
Apr 22, 2015
Dan Olson
Apr 22, 2015
bitwise
April 22, 2015
Hello!

I am trying to interface to C++, and getting linker errors. Below are my 3 source files and 2 build scripts with their associated errors. Can anyone see what I'm doing wrong?


/////////////////  test.cpp
#include <stdio.h>

class Test {
public:
	virtual void Foo(){
		printf("Foobar\n");
	}
};

Test* CreateTest() {
	return new Test;
}

void DestroyTest(Test *test) {
	delete test;
}

/////////////////  Test.d
module TestMod;

extern(C++) {
	interface Test {
		void Foo();
	}

	Test CreateTest();
	void DestroyTest(Test test);
}

/////////////////  main.d
module main;
import TestMod;

void main(string[] args)
{
	Test test = CreateTest();
	test.Foo();
	DestroyTest(test);
	test = null;
}

/////////////////  script1.sh
clang++ test.cpp -olibTest.o -c -emit-llvm
ar rcs libTest.a libTest.o
ldc2 main.d Test.d libTest.a -ofTest

Error:
Undefined symbols for architecture x86_64:
  "___Z10CreateTestv", referenced from:
      __Dmain in main.o
  "___Z11DestroyTestP4Test", referenced from:
      __Dmain in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Error: /usr/bin/gcc failed with status: 1


/////////////////  script2.sh
g++ test.cpp -olibTest.o -c
ar rcs libTest.a libTest.o
dmd main.d Test.d libTest.a -ofTest

Error:
Undefined symbols for architecture x86_64:
  "vtable for __cxxabiv1::__class_type_info", referenced from:
      typeinfo for Test in libTest.a(libTest.o)
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "operator delete(void*)", referenced from:
      DestroyTest(Test*) in libTest.a(libTest.o)
  "operator new(unsigned long)", referenced from:
      CreateTest() in libTest.a(libTest.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
--- errorlevel 1


April 22, 2015
bitwise <bitwise.pvt@gmail.com> writes:
> I am trying to interface to C++, and getting linker errors. Below are
> my 3 source files and 2 build scripts with their associated
> errors. Can anyone see what I'm doing wrong?

Hi, I think both examples need libstdc++ added when you link (-L-lstdc++).  That should resolve the missing C++ operators.

For script1.sh with ldc2 I see an extra underscore in C++ mangled names. You must be on OS X.  ldc was just fixed in merge-2.067 branch to remove an extra underscore on OS X.  If you want to experiment, you can build https://github.com/ldc-developers/ldc/tree/merge-2.067 and check it out. There are still a few tests to reolve, but it works pretty well for me.
--
Dan
April 22, 2015
On Wed, 22 Apr 2015 02:14:40 -0400, Dan Olson <zans.is.for.cans@yahoo.com> wrote:

> bitwise <bitwise.pvt@gmail.com> writes:
>> I am trying to interface to C++, and getting linker errors. Below are
>> my 3 source files and 2 build scripts with their associated
>> errors. Can anyone see what I'm doing wrong?
>
> Hi, I think both examples need libstdc++ added when you link
> (-L-lstdc++).  That should resolve the missing C++ operators.
>
> For script1.sh with ldc2 I see an extra underscore in C++ mangled names.
> You must be on OS X.  ldc was just fixed in merge-2.067 branch to remove
> an extra underscore on OS X.  If you want to experiment, you can build
> https://github.com/ldc-developers/ldc/tree/merge-2.067 and check it out.
> There are still a few tests to reolve, but it works pretty well for me.
> --
> Dan

Awesome, Thanks!

I am now getting the expected error from clang/LDC, and the GCC/DMD build is working. I'll probably switch to LDC at some point, but I just need to get up and running right now.

My updated(objective-C++) and working code:

///////////////// test.mm
#include <stdio.h>
#import <Foundation/Foundation.h>

@interface XYZPerson : NSObject
- (void)sayHello;
@end

@implementation XYZPerson
- (void)sayHello {
    printf("Hello, World!\n");
}
@end

class Test {
public:
	virtual void Foo(){
		XYZPerson *person = [[XYZPerson alloc] init];
		[person sayHello];
		[person release];
	}
};

Test* CreateTest() {
	return new Test;
}

void DestroyTest(Test *test) {
	delete test;
}

/////////////////  Test.d
same

/////////////////  main.d
same

///////////////// script2.sh
g++ test.mm -olibTest.o -c -stdlib=libc++
ar rcs libTest.a libTest.o
dmd main.d Test.d libTest.a -ofTest -L/usr/lib/libc++.dylib -L-framework -LFoundation
./Test