c++ 在服务器上打包 so 文件问题

2022-07-29 11:25:55 +08:00
 hhhhhh123
extern "C" __declspec(dllexport) float * OMP_EVAL(char* p1, char* p2, char* p3, char* p4, char* p5, char* p6, char* p7, char* p8, char* p9,
	char* _board, char* _dead, bool eval_or_monte_carlo
){
  // 省略函数里面代码..
}

上面这串导出代码 我在 win 本地是能编译成 dll 动态库的, 但是在服务器上面编译就报错了

main.cpp:13:22: error: expected constructor, destructor, or type conversion before ‘(’ token
   13 | extern "C" __declspec(dllexport) float * OMP_EVAL(char* p1, char* p2, char* p3, char* p4, char* p5, char* p6, char* p7, char* p8, char* p9,
      |                      ^
make: *** [Makefile:25: hongyu] Error 1
2249 次点击
所在节点    C
16 条回复
nifury
2022-07-29 11:34:08 +08:00
hmm 大概是 gcc 不支持__declspec(dllexport)?
能编译成 dll 不代表能编译成 so 啊
hhhhhh123
2022-07-29 11:35:31 +08:00
```
g++ -O3 -std=c++11 -Wall -Wpedantic -pthread -c -o omp/CardRange.o omp/CardRange.cpp
g++ -O3 -std=c++11 -Wall -Wpedantic -pthread -c -o omp/CombinedRange.o omp/CombinedRange.cpp
g++ -O3 -std=c++11 -Wall -Wpedantic -pthread -c -o omp/EquityCalculator.o omp/EquityCalculator.cpp
g++ -O3 -std=c++11 -Wall -Wpedantic -pthread -c -o omp/HandEvaluator.o omp/HandEvaluator.cpp
ar rcs lib/ompeval.a omp/CardRange.o omp/CombinedRange.o omp/EquityCalculator.o omp/HandEvaluator.o
g++ -O3 -std=c++11 -Wall -Wpedantic -pthread -shared -o hongyu.so main.cpp benchmark.cpp lib/ompeval.a
/usr/bin/ld: lib/ompeval.a(HandEvaluator.o): warning: relocation against `_ZN3omp13HandEvaluator8cardInitE' in read-only section `.text.startup'
/usr/bin/ld: /tmp/ccUEKBa8.o: relocation R_X86_64_PC32 against symbol `_ZSt4cout@@GLIBCXX_3.4' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:25: hongyu] Error 1
```
qbqbqbqb
2022-07-29 11:35:47 +08:00
GCC 编译器是没有__declspec(dllexport)的,建议用 ifdef 控制一下
hhhhhh123
2022-07-29 11:35:59 +08:00
@nifury 你知道这个错误吗? 我吧 extern "C" __declspec(dllexport) 删掉了
hhhhhh123
2022-07-29 11:36:23 +08:00
@qbqbqbqb 我删除 extern "C" __declspec(dllexport) 这个了,但是出现了上面的错误, 你知道吗
qbqbqbqb
2022-07-29 11:37:01 +08:00
@hhhhhh123 编译 so 的时候要加-fPIC 参数
qbqbqbqb
2022-07-29 11:37:40 +08:00
extern "C"不要随便删,只删__declspec(dllexport)
qbqbqbqb
2022-07-29 11:43:26 +08:00
@hhhhhh123 这个错误和 ompeval.a 这个静态库有关。一般情况下静态库和 so 动态库是不能混用的,除非静态库编译的时候加了-fPIC 参数才可以。如果可以的话就重新编译这个静态库。
qbqbqbqb
2022-07-29 11:51:42 +08:00
如果无法重新编译静态库的话,可以考虑改符号导出。需要保证接口函数(原来的加了 dllexport 的函数)里面不能直接调用 ompeval.a 静态库里的函数。

dllexport 在 Linux 环境的类似物是__attribute__ ((visibility ("default")))和__attribute__ ((visibility ("hidden")))。但是 GCC 默认选项是 default ,相当于默认全部 dllexport ,这里需要隐藏一些内部实现。

有两种方法:
第一种方法是编译加参数-fvisibility=hidden 修改为类似 Windows DLL 的默认不导出,然后在原来的 dllexport 的函数上加__attribute__ ((visibility ("default")))
第二种方法是给用到了 ompeval.a 静态库的内部函数加__attribute__ ((visibility ("hidden")))
hhhhhh123
2022-07-29 12:02:40 +08:00
@nifury @qbqbqbqb
@qbqbqbqb 我加了-fPIC 参数, 虽然能编译, 但是函数好像没有导出, 这个时候 应该怎么导出
yolee599
2022-07-29 12:35:25 +08:00
执行下面这个指令看看有没有导出?
nm -D <your .so file>
hhhhhh123
2022-07-29 13:47:35 +08:00
@yolee599 0000000000006710 T OMP_EVAL
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U _Unwind_Resume@GCC_3.0
0000000000007c40 T _Z9benchmarkv
000000000000b460 T _ZN3omp13CombinedRange10joinRangesERKSt6vectorIS1_ISt5arrayIhLm2EESaIS3_EESaIS5_EEm
000000000000ad90 T _ZN3omp13CombinedRange7shuffleEv
000000000000ae90 T _ZN3omp13CombinedRangeC1EjRKSt6vectorISt5arrayIhLm2EESaIS3_EE
000000000000ad00 T _ZN3omp13CombinedRangeC1Ev
000000000000ae90 T _ZN3omp13CombinedRangeC2EjRKSt6vectorISt5arrayIhLm2EESaIS3_EE
000000000000ad00 T _ZN3omp13CombinedRangeC2Ev
0000000000014930 T _ZN3omp13HandEvaluator10staticInitEv
00000000000164c0 R _ZN3omp13HandEvaluator11FLUSH_RANKSE
0000000000026460 B _ZN3omp13HandEvaluator11ORIG_LOOKUPE
0000000000022460 B _ZN3omp13HandEvaluator12FLUSH_LOOKUPE
00000000000147f0 T _ZN3omp13HandEvaluator14populateLookupEmjjjjjjb



还有很多这样的 , 次数超过限制所有发不出来
hhhhhh123
2022-07-29 13:49:01 +08:00
解决了 extern "C" 我删掉了 忘记加上去了, 所以没有导出来, 加上后 重新编译 函数也能导出来了。
proxytoworld
2022-07-29 13:52:17 +08:00
我用 cmake ,windows + gcc 编译成功..
环境 windows + cmake + gcc 8.1.0 seh
![]( )
proxytoworld
2022-07-29 13:52:57 +08:00
看错了,得编译 so
buffzty
2022-07-30 21:24:32 +08:00
加个 LIB_API 宏定义
#if defined WIN32 && !defined(BUFF_STATIC)
#ifdef LIB_EXPORTS
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif
#else
#define LIB_API
#endif
#ifdef __cplusplus
extern "C" {
#endif
LIB_API void libFn1();

#ifdef __cplusplus
}
#endif

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/869423

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX