Christian Wolf
Christian Wolf

Reputation: 1237

Why does matlab not link my C MEX code?

I have the following problem in compiling my mex C functions using MS VC++ Compiler: I have a function disc_rhs__ in a separate file disc_rhs.c which was createtd by f2c (which should be unimportant, but...). In my main function I write somewhere

...
disc_rhs__(...);
...

I try to compile using

mex sfun_kalman.cpp -L. -llapack -lcblas_WIN -lblas_WIN -lf2c disc_rhs.c kalmanfilter_f2c.cpp

This leads to an error. The linker cannot find the external symbol ""int __cdecl disc_rhs__(double *,double *,double *,double *,double *)" (?disc_rhs__@@YAHPAN0000@Z)" used in the kalmanfilter.cpp.

To get everything compiling I copied the disc_rhs.cppto disc_rhs.h and removed the function declaration just letting a stub. This I included in kalmanfilter.h.

So why does matlab mex compiler not recognize the corrct symbol and link with the compilation of disc_rhs.c?

Thanks Christian

Upvotes: 1

Views: 550

Answers (1)

Praetorian
Praetorian

Reputation: 109279

Do not put the entire contents of disc_rhs.cpp into a header file and then include it in another file. This will only work as long that file is being included by a single source file, as soon as you include it in another source file you'll get multiple definition errors.

The right way to fix this problem is to create a disc_rhs.h file that contains the prototypes of all functions from disc_rhs.cpp that need to be used by other modules. Then you'd include the header file in kalmanfilter.cpp (and any other files that need to use those functions).

EDIT:
The error is happening because the disc_rhs file has a .c extension which causes MSVC to compile it as a C file. However, since it is being used in kalmanfilter.cpp the linker is expecting to find a C++ function that has been name mangled, which doesn't exist. To fix the problem, you need to tell the compiler that disc_rhs__() is a C function.

In disc_rhs.h

#ifdef __cplusplus
extern "C" 
#endif
int disc_rhs__(double *,double *,double *,double *,double *);

The extern "C" directive needs to appear in front of each item being exported by disc_rhs.c, so if you have several things to extern, the following syntax is more convenient.

#ifdef __cplusplus
extern "C" {
#endif
int disc_rhs__(double *,double *,double *,double *,double *);

// other stuff being externed

#ifdef __cplusplus
}
#endif

Upvotes: 1

Related Questions