views:

203

answers:

2

There is a static class Pipe, defined in C++ header that I'm including.

The static method I'm interested in calling (from Objective-c) is here:

static ERC  SendUserGet(const UserId &_idUser,const GUID &_idStyle,const ZoneId &_idZone,const char *_pszMsg);

I have access to an objetive-c data structure that appears to store a copy of userID, and zoneID -- it looks like:

@interface DataBlock : NSObject
{
    GUID userID;
    GUID zoneID;
}

Looked up the GUID def, and its a struct with a bunch of overloaded operators for equality. UserId and ZoneId from the first function signature are #typedef GUID

Now when I try to call the method, no matter how I cast it (const UserId), (UserId), etc, I get the following linker error:

Ld build/Debug/Seeker.app/Contents/MacOS/Seeker normal i386
cd /Users/josh/Development/project/Mac/Seeker
setenv MACOSX_DEPLOYMENT_TARGET 10.5
/Developer/usr/bin/g++-4.2 -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk -L/Users/josh/Development/TS/Mac/Seeker/build/Debug -L/Users/josh/Development/TS/Mac/Seeker/../../../debug -L/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/gcc/i686-apple-darwin10/4.2.1 -F/Users/josh/Development/TS/Mac/Seeker/build/Debug -filelist /Users/josh/Development/TS/Mac/Seeker/build/Seeker.build/Debug/Seeker.build/Objects-normal/i386/Seeker.LinkFileList -mmacosx-version-min=10.5 -framework Cocoa -framework WebKit -lSAPI -lSPL -o /Users/josh/Development/TS/Mac/Seeker/build/Debug/Seeker.app/Contents/MacOS/Seeker

Undefined symbols:
  "SocPipe::SendUserGet(_GUID const&, _GUID const&, _GUID const&, char const*)", referenced from:
  -[PeoplePaneController clickGet:] in PeoplePaneController.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Is this a type/function signature error, or truly some sort of linker error? I have the headers where all these types and static classes are defined #imported -- I tried #include too, just in case, since I'm already stumbling :P

Forgive me, I come from a web tech background, so this c-style memory management and immutability stuff is super hazy.

Edit: Added full linker error text. Changed "function" to "method." Also I'll note that we're using a custom makefile to compile a few projects external to this one. SocPipe static methods are referenced elsewhere, though, in this xcode project and seems to compile fine.

Thanks, Josh

+1  A: 

(Eh, let's turn that comment into an answer.)

The method signature looks fine; that is, what you're calling matches what is declared in the header. If it was not, you would probably be getting a compilation error rather than a linker error.

The linker's problem is that it doesn't have any corresponding object code to connect this call to: the method is declared but never defined.

The latter should occur either in a C++ source file which your project can compile, or else in some precompiled library or framework that you can link to. Either way, that file needs to be included in your project so that it can be made available to the linker.

walkytalky
Ah. You pointed me to what the hell is wrong. In the implementation (which theoretically was included in the project), there is an ifdef thats precluding this particular block from being compiled. Argh! Maybe there's another method in the API that will serve my needs, I guess. Thanks much.
Josh
Ah, ok. Seems quite perverse for the whole method implementation to be #ifdef-ed out, since that breaks the interface.
walkytalky
+1  A: 

The object file containing Pipe::SendUserGet is not being built, or it is not being linked into your Xcode target. Whether or not other static methods in Pipe work correctly is not necessarily relevant if those methods are defined in the header file.

You mentioned that you use external makefiles to build parts of your project. In that case, it's not enough to run the makefile at compile time as a dependency — you also have to include the resulting products in your project.

For example, if you have a makefile that builds libLIBRARY.a, then drag libLIBRARY.a into your project and add it to your target.

This only works if the makefile is building a library. It won't work if the makefile builds a program. It also gets more complicated if the library is a dynamic library, as you'll also have to make sure that the dynamic library gets distributed with your application (often by putting it in the app bundle, if you're making an app bundle). It also gets more complicated if you want to build a universal binary. You could theoretically pass the right CFLAGS to make to build a universal library, but it may be easier to run make once for each architecture and combine the results using a script (which is what I do).

Dietrich Epp
Thanks for the additional detail. I think what happened here is that, in the rush of porting (from win32 to mac), this particular implementation got ifdef'd out as a TODO, and then they left the method def in the header for me to bash my head against. Huzzah! My fault for not knowing c/c++/objective-c well enough to know what the hell is going on.
Josh