如何调用包含的库函数?

问题描述 投票:0回答:1

我有这样的 C++ 共享库:

extern "C"{

   #include <foo.h>

   int test(int a){
      return 1;
   }

}

我可以查找和调用函数

int test(int a);
,但包含的库 (
foo.h
) 中导出的 C 函数无法调用。

如何使所有

foo.h
C 函数可见并调用它们?

我正在使用 CMake 来构建项目。

c++ c shared-libraries
1个回答
0
投票

我可以查找并调用函数 int test(int a);,但包含的库 (foo.h) 中导出的 C 函数不可见且无法调用。

您看不到您在头文件中定义的所有函数,因为它们未被使用。这是一个小例子:

// header_only.h
#ifndef HEADER_ONLY_H
#define HEADER_ONLY_H

extern "C" {

// these functions are used
inline int sum(int a, int b) { return a + b; }
inline int sub(int a, int b) { return a - b; }

// there functions are not
inline int mult(int a, int b) { return a * b; }

}

#endif // !HEADER_ONLY_H

我们来尝试调用其中的函数:

// test.cpp
#include "header_only.h"

extern "C" {

int test() {
  int a = 5;
  int b = 4;
  int add_result = sum(a, b);
  int sub_result = sub(a, b);

  return a * b;
}

}

请注意,我们只调用了

sum
sub
,而
mult
被定义但未被使用。

现在让我们编译目标文件并将其链接到库文件中:

# compile the source file into object file
❯ g++ -c  test.cpp -o test.o
# create a library file
❯ ar rcs libtest.a test.o
# print all symbol names
❯ nm -U libtest.a

test.o:
0000000000000074 T _sub
0000000000000054 T _sum
0000000000000000 T _test
0000000000000000 t ltmp0
0000000000000098 s ltmp1

如您所见,

mult
没有编译到lib中。如果我们编写一个像这样的
main
函数:

// test_lib.cpp
extern "C" {

extern int test();

int main() {
  test();
  return 0;
}
}

使用命令编译:

❯ g++ test_lib.cpp libtest.a -o main
❯ ./main
❯ echo $?
0

一切都会顺利进行。但如果您尝试直接在

mult
中使用
test_lib.cpp
而不包含
header_only.h
:

// test_lib.cpp
extern "C" {

int main() {
  // test();
  mult(3, 4);

  return 0;
}
}

让我们编译一下:

❯ g++ test_lib.cpp libtest.a -o main
test_lib.cpp:5:3: error: use of undeclared identifier 'mult'
  mult(3, 4);

如果你想使用你在头文件中定义的所有函数,最好的选择是将它们分成头文件和源文件,就像提到的这个答案一样。并用其他源文件编译您拆分出来的源代码(比方说

foo.cpp
)。

// header_only.h
#ifndef HEADER_ONLY_H
#define HEADER_ONLY_H

extern "C" {

// these functions are used
int sum(int a, int b);
int sub(int a, int b);

// there functions are not
int mult(int a, int b);
}

#endif // !HEADER_ONLY_H
//header_only.cpp
#include "header_only.h"

extern "C" {

int sum(int a, int b) { return a + b; }

int sub(int a, int b) { return a - b; }

int mult(int a, int b) { return a * b; }
}

其他源文件未修改。我们再编译一下:

❯ g++ -c header_only.cpp test.cpp
❯ ar rcs libtest.a test.o header_only.o
❯ nm -a libtest.a

test.o:
                 U _sub
                 U _sum
0000000000000000 T _test
0000000000000000 t ltmp0
0000000000000058 s ltmp1

header_only.o:
0000000000000040 T _mult
0000000000000020 T _sub
0000000000000000 T _sum
0000000000000000 t ltmp0
0000000000000060 s ltmp1

您可以看到所有符号都已导出。您可以在

mult
函数中使用
main

❯ cat test_lib.cpp
#include "header_only.h"

extern "C" {

int main() {
  // test();
  mult(3, 4);

  return 0;
}
}
❯ g++ libtest.a test_lib.cpp
❯ ./a.out
❯ echo $?
0

您可以在 CMake 中执行相同的操作。按照上面的操作,将你在

foo.h
中拆分出来的源代码的文件名添加到
add_library
中。

cmake_minimum_required(VERSION 3.17)

project(test_link)

add_library(link header_only.cpp test.cpp)

add_executable(main test_lib.cpp)
target_link_libraries(main link)

让我们构建项目:

❯ cmake -B build
cmake-- The C compiler identification is AppleClang 14.0.3.14030022
-- The CXX compiler identification is AppleClang 14.0.3.14030022
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/liuyuan/Desktop/test/build
❯ cmake --build build
[ 20%] Building CXX object CMakeFiles/link.dir/header_only.cpp.o
[ 40%] Building CXX object CMakeFiles/link.dir/test.cpp.o
[ 60%] Linking CXX static library liblink.a
[ 60%] Built target link
[ 80%] Building CXX object CMakeFiles/main.dir/test_lib.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
❯ ./build/main
❯ echo $?
0
© www.soinside.com 2019 - 2024. All rights reserved.