I've integrated the ZXing QR Code reader library (ZXingWidget) into my iPhone app, but it conflicts with a function from within the CocoaLumberjack logging library that I am also using.
Undefined symbols for architecture i386:
"ExtractFileNameWithoutExtension(char const*, signed char)", referenced from: ...
DDLog.h
NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
#define THIS_FILE (ExtractFileNameWithoutExtension(__FILE__, NO))
DDLog.m
NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy) { ...
As I call it in:
DDLogVerbose(#"%#:%#", THIS_FILE, THIS_METHOD);
The cause for this is that whichever Obj-C file contains the headers:
// import QR Code reader APIs
#import "ZXingWidgetController.h"
#import "QRCodeReader.h"
its file extension must be changed from .m to .mm for proper C++ support.
But then I lose my *DDLogVerbose(#"%#:%#", THIS_FILE, THIS_METHOD);* functionality.
What am I missing here to have these two play nice with each other?
If you're including C headers that aren't "C++-ified" into a C++ or Objective C++ file, you need to tell the compiler. Something like
extern "C" {
#include "DDlog.h"
}
in your .mms should work. Alternatively, if DDLog.h is your file, you can do something like
#ifdef __cplusplus
extern "C"
#endif
NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
A web search for "extern C" should provide more details/examples.
Related
C++ dylib exposes as follows
__attribute__((visibility("default"))) int addNumber(int number) {
return 0;
}
in my Swift project, I set the Import Paths dir to the dir containing my module.map file:
module MyLib {
header "myLib.h"
export *
}
I manually add myLib.h to my project:
#ifndef mylib_h
#define mylib_h
int addNumber(int number);
#endif
My main.swift does the following:
import Foundation
import MyLib
print("Hello, World!")
var result = addNumber(3)
When I compile the swift project, I can see that it links against my dylib (-lMyLib), but I get the following error:
Undefined symbols for architecture x86_64: "_addNumber", referenced
from:
_main 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)
So although it's linking correctly, it can't find the symbols.
I've verified both with nm (0000000000000d00 (__TEXT,__text) external addNumber) and Hopper that this function does exist in the dylib.
In the C++ library, your function must be marked with extern "C"
for C linkage:
extern "C" __attribute__((visibility("default"))) int addNumber(int number) {
return 0;
}
so that the compiler does not mangle the exported name. Swift can only
call C functions, not C++ functions.
See also What is the effect of extern "C" in C++?.
I have created C function:
header
//FileSystem.h file
#import <Foundation/Foundation.h>
BOOL AddSkipBackupAttributeToItemAtURL(NSURL *url);
implementation
//FileSystem.mm
#import "FileSystem.h"
#import <sys/xattr.h>
#import <Support/Support.h>
static const char* attrName = "com.apple.MobileBackup";
BOOL AddSkipBackupAttributeToItemAtURL(NSURL *url) {
BOOL operationResult = NO;
// some implementation
return operationResult;
}
When i'm calling AddSkipBackupAttributeToItemAtURL from another parts of application everything is OK, except one place where i'm calling function from the block.
__block UpdateFileAsyncOperation* selfOperation = self;
_contentDownloader.completionBlock = ^(NSData* data) {
[data saveForcedToPath:selfOperation.filePath];
NSURL* fileUrlWithScheme = [NSURL fileURLWithPath:selfOperation.filePath];
AddSkipBackupAttributeToItemAtURL(fileUrlWithScheme);
[runLoop removePort:port forMode:NSDefaultRunLoopMode];
[selfOperation completeOperation];
};
In that place ,while linking in progress, there is error:
Undefined symbols for architecture i386:
"AddSkipBackupAttributeToItemAtURL", referenced from:
__36-[UpdateFileAsyncOperation start]_block_invoke in UpdateFileAsyncOperation.o ld: symbol(s) not found for architecture
i386 clang: error: linker command failed with exit code 1 (use -v to
see invocation)
I don't understand why it happens, how it depends on block? and how can I fix that?
Thanks!
Update: it is not dependent on block, i have moved calling of function to another place of class: the error still there. I'm trying to find why
I have solved the problem.
It not dependent on block. It dependent on file extensions.
The problem file was with ".m" extension, other files was with ".mm" extension.
So I have putted next macro in FileSystem.h file
#ifdef __cplusplus
extern "C" {
#endif
BOOL AddSkipBackupAttributeToItemAtURL(NSURL *url);
#ifdef __cplusplus
}
#endif
I have some C classes imported into my app. So along with my .h and .m objective-c classes I have some .h and .c C++ classes. Is it ok to do this? Or do i need to compile them into a .a so they can be used?
Assuming its all ok to do what I have done, I want to call this C++ method
mms_t *mms_connect (mms_io_t *io, void *data, const char *url, const char *host, const char *uri,const char *query,int pport, int bandwidth)
So this method returns a struct called mms_t ?
It requires I pass in some char*.
In Objective-C what can i pass in here? Are there char* in this language? I'm guessing I cant pass in a NSString in its place?
I see from a little snippet of C code
strTemp = #"mms://123.30.49.85/htv2";
char *g_tcUrl = new char[[strTemp length] + 1];
'new' is used?
Whats the objective c equivalent of the above code?
Many Thanks,
-Code
First of all, you would have to change the type of your Objective-C file to Objective-C++. You can do this by changing the file extension to .mm or by using the file info panel (ctrl-click, get info).
For char*, you can convert an NSString to a C string using either UTF8String or cStringUsingEncoding: like this:
NSString *foo = #"Foo";
char *fooascii = [foo cStringUsingEncoding:NSASCIIStringEncoding];
char *fooutf8 = [foo UTF8String];
You can freely call across Objective C and C++, in fact mix them up in virtually any combination. All you need to do is convert types where appropriate. You will need your code files to be named .mm (technically Objective C++ files) not .m files to include C++ header files.
To convert Objective C string to C style strings do:
const char *cString = [strTemp cStringUsingEncoding:NSUTF8StringEncoding];
I have a C++ function which I call from Objective C.I need to pass variables by reference to the C++ function.But I get the following error in xcode - "Expected ';', ',' or ')' before '&' token in foo.h"
Function declaration in "foo.h"
#ifdef __cplusplus
extern "C"
{
#endif
NSString * LLtoUTM(double Lat,double Long,double &UTMNorthing, double &UTMEasting);
#ifdef __cplusplus
}
#endif
Function call in test_viewcontroller.m
double UTM_x;
double UTM_y;
UTMzone = [[NSString alloc] init];
UTMzone = (NSString *) LLtoUTM(latitude,longitude,UTM_y,UTM_x);
Can anyone tell me what is wrong?
Change the file to be test_viewcontroller.mm.
You told it to compile as an Objective-C file, which doesn't understand references. '.mm' means Objective-C++, which can mix the Obj-C and C++ together like what you're attempting to do.
You simply cannot do this in plain Objective-C — because references don't exist in C. They're a C++ feature. So you have to use Objective-C++, which basically means changing your Objective-C files' extensions to ".mm".
I have imported the pdf.h file in my view controller class and tried calling
NSString *outPutString = convertPDF(pathToPdfFile);
but while building it gives me linker error:
_convertPDF" refrenced from: -[ScriptViewController searchBarSearchButtonClicked:] in ScriptViewController.o Symbol(s) not found
I have also included libz.dylib in my project.
What am I doing wrong?
Is there any step to be followed before building the project which includes c code?
Also one more question:
Will this search algorithm work on any PDF(simple and formatted pdfs).
What if you change the name of the .m file that calls pdf.h to xxxx.mm ? It's a c++ file.
I tested it and found out it works only with simple ascii pdfs.
Your must use the definition in the pdf.h
#if __cplusplus
extern "C" {
#endif
NSString* convertPDF(NSString * pathToFile);
#if __cplusplus
}
#endif
also in the implementation file *pdf.m*m use:
#if __cplusplus
extern "C" {
#endif
NSString* convertPDF(NSString * pathToFile);
#if __cplusplus
} //Extern C
#endif