我想从C代码中调用一些C ++函数。我的项目中有三个文件:main.c
,cgal_kernel.cpp
和cgal_kernel.h
。
当我尝试编译它时,我遇到了编译错误。
这是三个文件。
cgal_kernel.h
typedef enum{
LEFT_TURN,
COLLINEAR,
RIGHT_TURN
} Orientation;
/* Given points p,q,r determine if the link p-q-r is a left turn, right-turn or collinear
*/
extern Orientation orientation_2 (double px, double py, double qx, double qy, double rx, double ry);
cgal_kernel.cpp
#include "cgal_kernel.h"
extern "C" Orientation orientation_2 (double px, double py, double qx, double qy, double rx, double ry)
{
return LEFT_TURN ;
}
main.c
#include <stdio.h>
#include "cgal_kernel.h"
int main(void)
{
double px = 0.0;
double py = 0.0;
double qx = 0.0;
double qy = 1.0;
double rx = 1.0;
double ry = 1.0;
Orientation test= orientation_2 ( px, py, qx, qy, rx, ry);
printf("Answer is %d\n", test);
return 0;
}
我想将cgal_kernel.cpp
编译为共享库文件,以便通过其外部函数接口从其他语言中使用。
我的编译步骤存储在bash脚本中
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
set -ex # Display compilation process.
rm -f *~ *.o *.so
g++ -c -Wall -Werror -fPIC cgal_kernel.cpp # Convert to object file
g++ -shared cgal_kernel.o -o libcgal_kernel.so
gcc -g -Wall main.c -o main -I. -L. -lcgal_kernel
运行上面的构建脚本后,我得到以下编译错误。
+ rm -f *~ *.o *.so
+ g++ -c -Wall -Werror -fPIC cgal_kernel.cpp
In file included from cgal_kernel.cpp:1:0:
cgal_kernel.h: In function ‘Orientation orientation_2(double, double, double, double, double, double)’:
cgal_kernel.h:17:20: error: previous declaration of ‘Orientation orientation_2(double, double, double, double, double, double)’ with ‘C++’ linkage
extern Orientation orientation_2 (double px, double py, double qx, double qy, double rx, double ry);
^
cgal_kernel.cpp:3:103: error: conflicts with new declaration with ‘C’ linkage
extern "C" Orientation orientation_2 (double px, double py, double qx, double qy, double rx, double ry)
我在哪里错了?我尝试从函数签名中的cgal_kernel.cpp文件中删除"C"
,然后我收到错误
+ rm -f *~ cgal_kernel.o libcgal_kernel.so
+ g++ -c -Wall -Werror -fPIC cgal_kernel.cpp
+ g++ -shared cgal_kernel.o -o libcgal_kernel.so
+ gcc -g -Wall main.c -o main -I. -L. -lcgal_kernel
/tmp/cclw7kGD.o: In function `main':
/home/gaurish/Dropbox/MyWiki/research_projects/MiCha/main.c:15: undefined reference to `orientation_2'
collect2: error: ld returned 1 exit status
似乎我犯了一些基本的错误,关于如何从C代码调用C ++函数,但我似乎无法弄清楚它!
修改
如果我将extern "C"
添加到cgal_kernel.h
和cgal_kernel.cpp
文件中的函数签名,我会收到以下错误:
+ rm -f *~ cgal_kernel.o libcgal_kernel.so
+ g++ -c -Wall -Werror -fPIC cgal_kernel.cpp
+ g++ -shared cgal_kernel.o -o libcgal_kernel.so
+ gcc -g -Wall main.c -o main -I. -L. -lcgal_kernel
In file included from main.c:2:0:
cgal_kernel.h:17:8: error: expected identifier or ‘(’ before string constant
extern "C" Orientation orientation_2 (double px, double py, double qx, double qy, double rx, double ry);
^
main.c: In function ‘main’:
main.c:15:3: warning: implicit declaration of function ‘orientation_2’ [-Wimplicit-function-declaration]
Orientation test= orientation_2 ( px, py, qx, qy, rx, ry);
^
答案 0 :(得分:1)
从C调用C ++代码的最简单方法是编写此表单的有效C / C ++头文件:
// header guard
#ifdef __cplusplus
extern "C" {
// alternatively, you could have separate C and C++ headers and have
// the extern "C" before each function in your C++ header
#endif
// Valid C header
#ifdef __cplusplus
}
#endif
然后继续使用C.在C ++中,按照通常的方式定义函数。
对于你的例子:
<强> cgal_kernel.h 强>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum{
LEFT_TURN,
COLLINEAR,
RIGHT_TURN
} Orientation;
/* Given points p,q,r determine if the link p-q-r is a left turn, right-turn or collinear
*/
Orientation orientation_2 (double px, double py, double qx, double qy, double rx, double ry);
#ifdef __cplusplus
}
#endif
<强> cgal_kernel.cpp 强>
#include "cgal_kernel.h"
Orientation orientation_2(double px, double py, double qx, double qy, double rx, double ry)
{
return LEFT_TURN ;
}
请注意,您的主文件应该是C ++文件,我们可以从How to mix C and C++
中读取答案 1 :(得分:1)
混合C和C ++代码时,请记住extern "C"
需要在C ++端,但在C端是INVALID SYNTAX。所以我通常在混合代码时使用宏:
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
然后对必须可以相互访问的任何函数的所有声明使用EXTERN_C
。这样,它对C编译器是不可见的,但避免了C ++编译器的名称修改。