How to use Objective-C utility methods (CC3Foundation.m) from Cocos3D static library in "mm" files (Objective-C++)?

0

I'm building a Cocos3D application that uses Cocos3D (Objective-C static lib) and Bullet Physics (C++ static lib) in iOS.

So most of my code files are ".mm" files (Objective-C++), to use both Objective-C methods and C++ functions, with "-ObjC -lstdc++" linker flags in the target build option.

The problem is: in the "mm" files, calling the utility methods from "CC3Foundation.m" in Cocos3D static library causes link error ("undefined symbol"). Calling other Cocos3D's class methods in Cocos3D does not have any problem.

"CC3Foundation.m" in Cocos3D is a file of utility methods (not class member methods) that can be used by other Objective-C classes. It doesn't have any class declaration/implementation.

// TestClass.h ("h" header file)
@interface TestClass
...
-(void) testMethod;
...
@end

// TestClass.mm ("mm" file)
#import "CC3Foundation.h"
@implementation TestClass
...
-(void) testMethod{
  CC3Vector va[2];
  
  // "NSStringFromCC3Vectors()" from "CC3Foundation.m" in Cocos3D static library.
  // Undefined symbol: NSStringFromCC3Vectors(CC3Vector*, unsigned int)
  NSLog(@"va: %@", NSStringFromCC3Vectors(va,2)); // link error

}
...
@end



// from cocos3D static library

// CC3Foundation.h
NSString* NSStringFromCC3Vectors(CC3Vector* vectors, GLuint vectorCount);

// CC3Foundation.m
NSString* NSStringFromCC3Vectors(CC3Vector* vectors, GLuint vectorCount) {
    NSMutableString* desc = [NSMutableString stringWithCapacity: (vectorCount * 8)];
    for (GLuint vIdx = 0; vIdx < vectorCount; vIdx++)
        [desc appendFormat: @"\n\t%@", NSStringFromCC3Vector(vectors[vIdx])];
    return desc;
}

Calling this "NSStringFromCC3Vectors()" utility method in "m" files (Objective-C) does not have any issues at all. The error occurs in "mm" files only (Objective-C++). I had rebuilt Cocos3D static library, with "-lstdc++" option, but nothing changes. Still the methods in mm-files have "undefined symbol" link-error.

As far as I know it should be a minor issue regarding how to mix codes of Objective-C and C++, that can be fixed easily (hopefully). Otherwise, I have no other option but to change the architecture of my app to use "m" files instead of "mm". It will be much appreciated if any helpful answers could be provided. Thanks.

Configuration Information:

Cocos3D v2.2 (0x020002), Cocos2D v3.21 (0x00030201)

Bullet Physics Engine: v2.88

Xcode:12.0.1, iOS: 12.4.8

// Update (Solved).

It is solved now by specifying extern "C" linkage to include the header file "CC3Foundation.h" correctly according to "C", not "C++". Basically "CC3Foundation.m" is "C" function file, and the compiler and linker need to know because C and C++ have different symbol name handling mechanism. So, without extern "C" linkage, the linker fails to find the symbol names of the functions in "CCFoundation.m" from the static library so the linker error occurs.

// TestClass.mm ("mm" file)

// Use extern "C" linkage to let compiler/linker know "CCFoundation.h/m" is "C" function files.
// Must import "CC3Foundation.h" first 
// because "CC3Foundation" is also imported in other classes 
// and those classes are also imported in this mm file.
extern "C" {
#import "CC3Foundation.h"
}

@implementation TestClass
...
-(void) testMethod{
  CC3Vector va[2];

  // "NSStringFromCC3Vectors()" from "CC3Foundation.m" in Cocos3D static library.
  NSLog(@"va: %@", NSStringFromCC3Vectors(va,2)); // no linker error

}
...
@end

One of Objective-C++ files in Cocos3D, "CC3VertexArraysPODExtensions.mm" uses "CC3Foundation.h/m" and it imports "CC3Foundation.h" in the same way.

Helpful post regarding extern "C"

What is the effect of extern "C" in C++?

objective-c
objective-c++
bulletphysics
cocos3d
asked on Stack Overflow Oct 22, 2020 by s4mt6 • edited Oct 23, 2020 by s4mt6

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0