Question

I have been trying to get my head around some errors I get when compiling a MATLAB function written in C (on Mac OS X). The function msound is provided precompiled for Windows and Linux by my university and is the basis for some further functions concerning audio recording and playback. Since I'm a Mac-User I thought it would be pretty neat to have it compiled into a Mac-version, too.

From the sourcecode and its compiler-function for Linux I tried to reverse-engineer a Mac-Version of the compiler-instructions, but I keep getting errors resulting in a failed compilation. Here is what I put together as compiler-function so far:

function compile_msound_unix

disp('Building msound ...')

szOptions = '';
szDefines = '';
szPaths   = '';
szFiles   = '';
szLibs    = '';

szOptions = sprintf( '%s %s', szOptions, '-output msound'       );
szOptions = sprintf( '%s %s', szOptions, '-largeArrayDims'      );

% Add main file.
szFiles = addFile( szFiles, 'msound.c' );

% Add basic PortAudio include paths and files.
szPaths = addPath( szPaths, 'portaudio/include'                         );
szPaths = addPath( szPaths, 'portaudio/src/common'                      );
szPaths = addPath( szPaths, 'portaudio/src/os/unix'                     );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_allocation.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_converters.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_cpuload.c'         );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_debugprint.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_dither.c'          );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_front.c'           );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_process.c'         );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_ringbuffer.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_skeleton.c'        );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_stream.c'          );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_trace.c'           );
% Host
szFiles = addFile( szFiles, 'portaudio/src/os/unix/pa_unix_hostapis.c'  );
szFiles = addFile( szFiles, 'portaudio/src/os/unix/pa_unix_util.c'      );

% Add PortAudio path for: Apple Core Audio API
disp('    Using ''Apple Core Audio API'' ...')

% Defines
szDefines = addDefine( szDefines, 'PA_USE_COREAUDIO' );
szDefines = addDefine( szDefines, '__MACOSX_CORE__');
% PortAudio
szPaths = addPath( szPaths, 'portaudio/src/hostapi/coreaudio' );
szFiles = addFile( szFiles, 'portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c' );
szFiles = addFile( szFiles, 'portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c' );
szFiles = addFile( szFiles, 'portaudio/src/hostapi/coreaudio/pa_mac_core.c' );
% Libs
% szLibs  = addLib ( szLibs , '/full/path/to/library?' );

% Build msound MEX-file using default compiler.
eval( [ 'mex', szOptions, szDefines, szPaths, szFiles, szLibs ] );

function szCmd = addFile  ( szCmd, szFile )
    szCmd = sprintf( '%s "%s"'  , szCmd, szFile );
function szCmd = addPath  ( szCmd, szPath )
    szCmd = sprintf( '%s "-I%s"', szCmd, szPath );
function szCmd = addDefine( szCmd, szName )
    szCmd = sprintf( '%s "-D%s"', szCmd, szName );
function szCmd = addLib   ( szCmd, szLib  )
    szCmd = sprintf( '%s "-l%s"', szCmd, szLib  );
function szCmd = addLibPath( szCmd, szPath )
    szCmd = sprintf( '%s "-L%s"', szCmd, szPath )

I already eliminated a few other errors, but right now I'm stuck with the following MATLAB console output:

Building msound ...
    Using 'Apple Core Audio API' ...
msound.c: In function 'msoundDeviceInfo':
msound.c:3042: warning: initialization makes pointer from integer without a cast
msound.c:3044: warning: initialization makes pointer from integer without a cast
msound.c:3046: warning: initialization makes pointer from integer without a cast
msound.c:3048: warning: initialization makes pointer from integer without a cast
portaudio/src/hostapi/coreaudio/pa_mac_core.c: In function 'AudioIOProc':
portaudio/src/hostapi/coreaudio/pa_mac_core.c:1911: warning: 'AudioConverterFillBuffer' is deprecated (declared at /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AudioToolbox.framework/Headers/AudioConverter.h:641)
portaudio/src/hostapi/coreaudio/pa_mac_core.c:2080: warning: 'AudioConverterFillBuffer' is deprecated (declared at /Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/AudioToolbox.framework/Headers/AudioConverter.h:641)
Undefined symbols for architecture x86_64:
  "_mxCreateScalarDouble", referenced from:
      _msoundDeviceInfo in msound.o
  "_AudioDeviceSetProperty", referenced from:
      _setBestFramesPerBuffer in pa_mac_core_utilities.o
      _AudioDeviceSetPropertyNowAndWaitForChange in pa_mac_core_utilities.o
     (maybe you meant: _AudioDeviceSetPropertyNowAndWaitForChange)
  "_AudioDeviceGetProperty", referenced from:
      _setBestFramesPerBuffer in pa_mac_core_utilities.o
      _AudioDeviceSetPropertyNowAndWaitForChange in pa_mac_core_utilities.o
      _setBestSampleRateForDevice in pa_mac_core_utilities.o
      _GetChannelInfo in pa_mac_core.o
      _PaMacCore_Initialize in pa_mac_core.o
      _OpenStream in pa_mac_core.o
      _PaMacCore_GetChannelName in pa_mac_core.o
      ...
  "_AudioDeviceGetPropertyInfo", referenced from:
      _setBestFramesPerBuffer in pa_mac_core_utilities.o
      _setBestSampleRateForDevice in pa_mac_core_utilities.o
      _GetChannelInfo in pa_mac_core.o
      _PaMacCore_Initialize in pa_mac_core.o
      _PaMacCore_GetChannelName in pa_mac_core.o
  "_AudioDeviceAddPropertyListener", referenced from:
      _AudioDeviceSetPropertyNowAndWaitForChange in pa_mac_core_utilities.o
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioDeviceRemovePropertyListener", referenced from:
      _AudioDeviceSetPropertyNowAndWaitForChange in pa_mac_core_utilities.o
      _CloseStream in pa_mac_core.o
  "_AudioHardwareGetPropertyInfo", referenced from:
      _PaMacCore_Initialize in pa_mac_core.o
  "_AudioHardwareGetProperty", referenced from:
      _PaMacCore_Initialize in pa_mac_core.o
  "_AudioUnitUninitialize", referenced from:
      _CloseStream in pa_mac_core.o
  "_CloseComponent", referenced from:
      _CloseStream in pa_mac_core.o
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioConverterDispose", referenced from:
      _CloseStream in pa_mac_core.o
  "_AudioConverterReset", referenced from:
      _StartStream in pa_mac_core.o
  "_AudioOutputUnitStart", referenced from:
      _StartStream in pa_mac_core.o
  "_AudioOutputUnitStop", referenced from:
      _StopStream in pa_mac_core.o
      _AudioIOProc in pa_mac_core.o
  "_AudioUnitGetProperty", referenced from:
      _StopStream in pa_mac_core.o
      _startStopCallback in pa_mac_core.o
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioUnitReset", referenced from:
      _StopStream in pa_mac_core.o
  "_AudioDeviceGetCurrentTime", referenced from:
      _GetStreamTime in pa_mac_core.o
      _AudioIOProc in pa_mac_core.o
  "_FindNextComponent", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_OpenAComponent", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioUnitSetProperty", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioUnitAddPropertyListener", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioConverterNew", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioConverterSetProperty", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioUnitInitialize", referenced from:
      _OpenAndSetupOneAudioUnit in pa_mac_core.o
  "_AudioUnitRender", referenced from:
      _AudioIOProc in pa_mac_core.o
  "_AudioConverterFillBuffer", referenced from:
      _AudioIOProc in pa_mac_core.o
  "_CFStringCreateWithFormat", referenced from:
      _PaMacCore_GetChannelName in pa_mac_core.o
  "_CFStringGetLength", referenced from:
      _PaMacCore_GetChannelName in pa_mac_core.o
  "_CFStringGetCString", referenced from:
      _PaMacCore_GetChannelName in pa_mac_core.o
  "_CFRelease", referenced from:
      _PaMacCore_GetChannelName in pa_mac_core.o
  "___CFConstantStringClassReference", referenced from:
      CFString in pa_mac_core.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

    mex: link of ' "msound.mexmaci64"' failed.

??? Error using ==> mex at 208
Unable to complete successfully.

Error in ==> compile_msound_unix at 51
eval( [ 'mex', szOptions, szDefines, szPaths, szFiles, szLibs ] );

The major problem seems to be the Undefined symbols for architecture x86_64. I did some research on that, I now know that some frameworks might be missing. But I'm very new to this kind of programming (and compiling on the Mac) and I could use some help.

The function I try to compile is based on the PortAudio Audio-I/O which supports CoreAudio on the Mac. As you see in my compiler-function, I already included the files of PortAudio which are necessary, but I'm still missing the corresponding Libraries/Frameworks. I already tried to provide them with lines like:

szLibs  = addLib ( szLibs , '/System/Library/Frameworks/CoreAudio.framework' ); 

but without any success. I really hope you guys have ideas how to make this run. I am using Mac OS X 10.7.3 Lion, and I have Xcode installed and gcc-4.2 is running. MATLAB Version is 2011a (v7.12)

Thanks in advance, Jan.

Was it helpful?

Solution

Heureka! I finally found it out myself: Since I simply took a lot of the code from the Linux mex-compiling-function of msound, the problem was how the neccesary frameworks were linked in. As it turns out that the " ... " (double quotes) at the paths and files were wrong for it to work, and only the frameworks actually need them because they get passed along to gcc. I removed them from the addFile, addPath and so on and finally all files got recognized and the frameworks linked, so that all the missing symbols went away. My epiphany was mostly initiated by this Stackoverflow question and specifically its correct answer.

In case of interest, here is the fully working compiler-function:

    function compile_msound_mac

bOldMexApi = false;

disp('Building msound ...')

szOptions = '';
szDefines = '';
szPaths   = '';
szFiles   = '';
szFrameworks    = 'LDFLAGS="\$LDFLAGS';

szOptions = sprintf( '%s %s', szOptions, '-output msound'       );

% Use the old MATLAB C API on newer MATLAB versions.
if( ~verLessThan('matlab','7.3') )
    if( bOldMexApi )
        % Use backward compatible old MATLAB C API
        szOptions = sprintf( '%s %s', szOptions, '-compatibleArrayDims' );
    else
        szOptions = sprintf( '%s %s', szOptions, '-largeArrayDims'      );
    end
end

% Add main file.
szFiles = addFile( szFiles, 'msound.c' );

% Add basic PortAudio include paths and files.
szPaths = addPath( szPaths, 'portaudio/include'                         );
szPaths = addPath( szPaths, 'portaudio/src/common'                      );
szPaths = addPath( szPaths, 'portaudio/src/os/unix'                     );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_allocation.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_converters.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_cpuload.c'         );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_debugprint.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_dither.c'          );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_front.c'           );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_process.c'         );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_ringbuffer.c'      );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_skeleton.c'        );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_stream.c'          );
szFiles = addFile( szFiles, 'portaudio/src/common/pa_trace.c'           );
% Host
szFiles = addFile( szFiles, 'portaudio/src/os/unix/pa_unix_hostapis.c'  );
szFiles = addFile( szFiles, 'portaudio/src/os/unix/pa_unix_util.c'      );

% Add PortAudio path for: Apple Core Audio API
disp('    Using ''Apple Core Audio API'' ...')
% Defines
szDefines = addDefine( szDefines, 'PA_USE_COREAUDIO' );
szDefines = addDefine( szDefines, '__MACOSX_CORE__');
% PortAudio
szPaths = addPath( szPaths, 'portaudio/src/hostapi/coreaudio'                        );
szFiles = addFile( szFiles, 'portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c' );
szFiles = addFile( szFiles, 'portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c');
szFiles = addFile( szFiles, 'portaudio/src/hostapi/coreaudio/pa_mac_core.c '         );
% Frameworks
szFrameworks = addFramework ( szFrameworks , 'CoreAudio'     );
szFrameworks = addFramework ( szFrameworks , 'AudioToolbox'  );
szFrameworks = addFramework ( szFrameworks , 'AudioUnit'     );
szFrameworks = addFramework ( szFrameworks , 'CoreServices'  );
% 
% 
% % Closing Tag for Frameworks
szFrameworks = sprintf('%s"', szFrameworks);

% Build msound MEX-file using default compiler.
eval( [ 'mex', szOptions, szDefines, szPaths, szFiles , szFrameworks ] )

disp('Done.')

function szCmd = addFile  ( szCmd, szFile )
    szCmd = sprintf( '%s %s'  , szCmd, szFile );
function szCmd = addPath  ( szCmd, szPath )
    szCmd = sprintf( '%s -I%s', szCmd, szPath );
function szCmd = addDefine( szCmd, szName )
    szCmd = sprintf( '%s -D%s', szCmd, szName );
function szCmd = addFramework( szCmd, szFramework)
    szCmd = sprintf( '%s -framework %s', szCmd, szFramework);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top