Question

I was trying to add AMR-NB decoding support to an iOS app, which has been successfully done before. But since I upgraded the framework I used (PhoneGap, now as Cordova), I started a new project and migrate all codes to the new one, the AMR-NB lib starts to make error during linking phrase.

enter image description here

I've been checking the .a lib file with 'file' and 'lipo -info' command, and made sure the fat lib contains arch for i386, and it's already included in the linking phrase in build phrases. I've been comparing the build settings of the new and old project, but found no luck to solve this.

Does anyone know where I might got it wrong? Thx!

Update: Added the fragment of code of amrFileCodec.h and CJ-Func.m

The amrFileCodec.h

//  amrFileCodec.h
//  Created by Tang Xiaoping on 9/27/11.
//  Copyright 2011 test. All rights reserved.

#ifndef amrFileCodec_h
#define amrFileCodec_h
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "interf_dec.h"
#include "interf_enc.h"

...

// 将AMR文件解码成WAVE文件
int DecodeAMRFileToWAVEFile(const char* pchAMRFileName, const char* pchWAVEFilename);

#endif

The CJ-Func.m

//  CJ-Func.m
//  iBear
//  Created by Chris Jiang on 11-4-22.
//  Copyright 2011 Individual. All rights reserved.

#import "CJ-Func.h"
#import "interf_dec.h"
#import "interf_enc.h"
#import "amrFileCodec.h"

@implementation MyPGPlugFunc

...

- (void)decodeAMR:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
    NSArray *currentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *basePath = [currentPaths objectAtIndex:0];
    NSString *wavDir = [basePath stringByAppendingPathComponent:@"tmp/wav"];
    NSString *wavPath = [basePath stringByAppendingPathComponent:[arguments objectAtIndex:1]];

    NSLog(@"[CJ-FUNC] Decoding %@ to %@", [arguments objectAtIndex:0], wavPath);

    BOOL isDir = YES;
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    if ( ![fileMgr fileExistsAtPath:wavDir isDirectory:&isDir] ) {
        if ( ![fileMgr createDirectoryAtPath:wavDir withIntermediateDirectories:YES attributes:nil error:nil] )
            NSLog(@"[CJ-FUNC] ERROR: tmp/wav directory creation failed");
        else
            NSLog(@"[CJ-FUNC] tmp/wav directory created");
    }
    [fileMgr release];

    int encRes = DecodeAMRFileToWAVEFile(
        [[arguments objectAtIndex:0] cStringUsingEncoding:NSASCIIStringEncoding], 
        [wavPath cStringUsingEncoding:NSASCIIStringEncoding]
    );

    if ( encRes <= 0 )
        [self writeJavascript:[NSString stringWithFormat:@"%@();", [arguments objectAtIndex:3]]];
    else
        [self writeJavascript:[NSString stringWithFormat:@"%@('%@');", [arguments objectAtIndex:2], wavPath]];
}

@end
Was it helpful?

Solution

The message "Undefined symbols for architecture i386" doesn't mean that your library is missing the i386 architecture. The important part is the next line:

"_DecodeAMRFileToWaveFile", referenced from -[MyPGPlugFunc decodeAMR:withDict:] in CJ-Func.o

It sounds like you have a function DecodeAMRFileToWaveFile(), which is defined in an Obj-C++ .mm file, but you're trying to use it from a .m file. So you're running into the difference between the way C compiles functions vs. how C++ does it. You need to tell C++ to make the function look like a plain C function.

You need this in your header file:

#ifdef __cplusplus
extern "C" {
#endif

void DecodeAMRFileToWaveFile();  // or whatever its declaration is

#ifdef __cplusplus
}
#endif

Here's a reference in the C++ FAQ, and a more detailed explanation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top