2

Question: How do I use PCL in the context of an Objective-C Cocoa (OSX, not iOS) app?

Tearing my hair out over this one.I can't get libpcl to link properly with my Objective C project in Xcode. I have checked and re-checked everything I can possibly think of. Probably doing something dumb, but I'm stumped.

Actual error is linker:

Undefined symbols for architecture x86_64:
"pcl::PassThrough<pcl::PointXYZ>::applyFilterIndices(std::__1::vector<int, std::__1::allocator<int> >&)", referenced from:
 pcl::PassThrough<pcl::PointXYZ>::applyFilter(std::__1::vector<int, std::__1::allocator<int> >&) in PCLProcess.o
 ld: symbol(s) not found for architecture x86_64
  • The code I'm trying to compile is the standard tutorial code available here: http://pointclouds.org/documentation/tutorials/passthrough.php#passthrough

  • I CAN get it to work without Xcode (using Cmake and command line compiling exactly as in the tutorial)

  • I CAN create a "command line" project and compile and link a one-off CPP file using Xcode

  • The issue is the same no matter what version of PCL I've tried. Macports, binary distro, self-compiled 1.6 and trunk. All the same result.

  • I've tried several different machines, OSX 10.7 and 10.8, same issue on both.

  • I've even run nm against the dylib to verify the missing symbols are in the library I'm linking (filters in this case)

Any thoughts much appreciated, I've lost half a week to this.

See this screenshot for a detailed error message.

Here is the code in question:

//PCLProcess.h
#import <Foundation/Foundation.h>
@interface PCLProcess : NSObject
@end

//PCLProcess.mm
#import "PCLProcess.h"
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>

@implementation PCLProcess

-(void)tryThis{
   // Code cut and pasted from tutoral (see link above)
}

@end

Update

Here is one more clue. I am in over my head with respect to compilers/linkers and how they work, but now I think I know what is happening but not why (or how to fix it).

  • I ran the linker tool manually, and out of desperation I started plugging in obsolete flags just to see what the results were. The previous error (above) identifies the missing symbols as ""pcl::PassThrough::applyFilterIndices(std::__1::vector >&)" but ld -y gave me this:

    ld: warning: option -y is obsolete and being ignored Undefined symbols for architecture x86_64:"__ZN3pcl11PassThroughINS_8PointXYZEE18applyFilterIndicesERNSt3__16vectorIiNS3_9allocatorIiEEEE", referenced from:__ZN3pcl11PassThroughINS_8PointXYZEE11applyFilterERNSt3__16vectorIiNS3_9allocatorIiEEEE in PCLProcess.o ld: symbol(s) not found for architecture x86_64

So then I went looking for that symbol and, sure enough, it's missing (or different):

nm /opt/local/lib/libpcl_filters.dylib | grep __ZN3pcl11PassThroughINS_8PointXYZEE18applyFilterIndices
00000000000a0fa0 
T  __ZN3pcl11PassThroughINS_8PointXYZEE18applyFilterIndicesERSt6vectorIiSaIiEE

I suspect name mangling? But again, I'm not really sure what I'm talking about at this point or (more importantly) how to fix it.

andrew
  • 218
  • 3
  • 12
  • Seems you have ObjC++ header pollution. Remember to use the .mm extension for files that reference anything in a C++ context like PCL – CodaFi May 01 '13 at 14:07
  • I suspected something like that initially from earlier problem using cinder (also C++) in the same project. I'm using mm but I still might have missed something... I'll edit the Q and include the troubled code. – andrew May 01 '13 at 14:13

1 Answers1

2

Short answer:

Two Build settings under "Build Options":

C++ Language Dialect: GNU++98[-std=gnu++98]

C++ Standard Library: libstdc++ (GNU C++ standard library)

This second setting (C++ Standard Library) is the crucial one; Using libc++ will produce the "undefined symbols" linker errors shown in the question above.

Details for anyone trying this:

This works with Xcode 4.62, llvm4.2, libpcl 1.7 (currently dev, I compiled from trunk) and boost 1.53. Along the way I ran into a known issue with Boost and Cocoa involving the use of nil (see this link:https://svn.boost.org/trac/boost/ticket/5010) and also some strangeness with boost traits (see this:c++: Boost 1.48 type traits and Cocoa inclusion weirdness) Consequently I ended up including PCL headers as follows:

#define nil Boost_nil
#define Nil Boost_Nil
#ifdef check
#undef check
#endif

#include <pcl/pcl_base.h>
#include <pcl/point_types.h>
#include <pcl/filters/passthrough.h>

#undef Nil
#undef nil
Community
  • 1
  • 1
andrew
  • 218
  • 3
  • 12
  • If anyone can explain WHY this is true (changing the standard library causes the linker to find/not find symbols in dynamic libraries), I would be grateful. In particular, the same project is making use of other libraries that would prefer C11 and libstdc (I would too!). – andrew May 02 '13 at 23:56
  • Which standard lib did you link libpcl against? Many libraries default to libstdc++ – Chris Devereux May 03 '13 at 01:20
  • Thanks for that... I thought that I had linked PCL against libc++, but I double checked and it was libstd (in fact I wasn't actually able to compile PCL itself out of the box against libc++ but that's another issue). Just so I'm clear, is this generally true (that you must compile your project against the same standard lib that your libraries were compiled against)? This makes it awfully difficult to mix libraries unless they can all compile the same way (and unless you actually know what standard lib they used if they arrive as binaries), but at least it explains what I was up against. – andrew May 03 '13 at 19:35
  • Yup. You've encountered one of the most annoying aspects of c++, I'm afraid. See http://stackoverflow.com/questions/8454329/why-cant-clang-with-libc-in-c0x-mode-link-this-boostprogram-options-examp for an explanation. – Chris Devereux May 06 '13 at 14:32
  • Yuck! But thanks a lot for the info/link, at least I understand the issue. – andrew May 08 '13 at 08:09