2017-04-06 49 views
0

我想从C代码调用一些C++函数。我的项目中有三个文件:main.ccgal_kernel.cppcgal_kernel.h从C代码调用C++函数的问题

当我尝试编译它们时出现编译错误。

以下是三个文件。

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代码调用,但我似乎无法弄清楚!


编辑: 如果我在这两个cgal_kernel.hcgal_kernel.cpp文件,我得到以下错误添加extern "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 
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); 
^
+5

外部“C”需要在声明中,而不是定义(我认为它可以在两者中) – Justin

+2

@Justin,你需要一些'#if'或宏来确保它只适用于C++环境,因为C没有'extern“C''。 –

+0

@Justin请参阅编辑。我仍然通过在头文件中添加'extern“C”'来获得错误 – smilingbuddha

回答

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

混合C和C++代码时阅读,请记住,extern "C"需要在C++的结束,但C端无效语法。所以一般我用宏混合代码时:

#ifdef __cplusplus 
#define EXTERN_C extern "C" 
#else 
#define EXTERN_C 
#endif 

然后在任何函数的所有声明必须是相互访问使用EXTERN_C。这样一来,它对C编译器来说是不可见的,但是避免了C++编译器的名称混乱。