0

有一个静态类 Pipe,在我包含的 C++ 头文件中定义。

我有兴趣调用的静态方法(来自 Objective-c)在这里:

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

我可以访问一个似乎存储用户 ID 和 zoneID 副本的 Objective-c 数据结构——它看起来像:

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

查找了 GUID def,它是一个结构,其中包含一堆用于相等的重载运算符。第一个函数签名中的 UserId 和 ZoneId 是 #typedef GUID

现在,当我尝试调用该方法时,无论我如何转换它(const UserId)、(UserId)等,我都会收到以下链接器错误:

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

这是类型/函数签名错误,还是真正的某种链接器错误?我有定义所有这些类型和静态类的标题#imported - 我也尝试了#include,以防万一,因为我已经绊倒了:P

原谅我,我来自网络技术背景,所以这种 c 风格的内存管理和不变性的东西是超级模糊的。

编辑:添加了完整的链接器错误文本。将“功能”更改为“方法”。另外我会注意到,我们正在使用一个自定义的 makefile 来编译这个之外的一些项目。不过,在这个 xcode 项目中,SocPipe 静态方法在其他地方被引用,并且似乎编译得很好。

4

2 回答 2

1

(嗯,让我们把这个评论变成一个答案。)

方法签名看起来不错;也就是说,您所调用的内容与标题中声明的内容相匹配。如果不是,您可能会收到编译错误而不是链接器错误。

链接器的问题是它没有任何相应的目标代码可以将此调用连接到:该方法已声明但从未定义

后者应该出现在您的项目可以编译的 C++ 源文件中,或者出现在您可以链接到的某些预编译库或框架中。无论哪种方式,该文件都需要包含在您的项目中,以便链接器可以使用它。

于 2010-05-15T23:35:44.550 回答
1

包含的目标文件Pipe::SendUserGet没有被构建,或者它没有被链接到您的 Xcode 目标中。如果在头文件中定义了这些方法,则其他静态方法Pipe是否正常工作不一定相关。

您提到您使用外部生成文件来构建项目的一部分。在这种情况下,仅在编译时将 makefile 作为依赖项运行是不够的——您还必须在项目中包含生成的产品。

例如,如果您有一个构建文件libLIBRARY.a,则将其拖入libLIBRARY.a您的项目并将其添加到您的目标中。

这仅在 makefile 正在构建库时才有效。如果 makefile 构建程序,它将无法工作。如果库是动态库,它也会变得更加复杂,因为您还必须确保动态库与您的应用程序一起分发(通常通过将其放入应用程序包中,如果您正在制作应用程序包) . 如果您想构建通用二进制文件,它也会变得更加复杂。理论上你可以传递正确的 CFLAGS 来make构建一个通用库,但是为每个架构运行一次并使用脚本组合结果可能更容易make(这就是我所做的)。

于 2010-05-15T23:43:11.703 回答