如何访问和使用共享库中定义的字符串

问题描述

我试图将版本字符串烘烤到共享库中,但无法弄清楚如何在该库的客户端程序中访问该字符串。

我要使用的方法是:将版本字符串保存在文本文件version.txt中,使用objcopy将该版本字符串转换为目标文件,将其链接.so并将客户端程序链接到动态共享库。

这是我的代码

version.txt

1.2.3.4

test.cpp

#include <iostream>
extern size_t _binary_version_txt_size;
int main() { std::cout << "Size: " << _binary_version_txt_size << std::endl; }

makefile

# abbreviate the tools we'll use
CXX:=g++-8
OC:=objcopy

# set up the compile and link options
CXXFLAGS:=-std=c++17 -Wall -pedantic -fPIC -g

# identify phony targets
.PHONY: clean

# set the default targets
all: test

# recipe to convert text files to object files
%.o: %.txt
    $(OC) --input binary --output elf64-x86-64 --binary-architecture i386:x86-64 $< $@

# recipes for building objects from source files
%.o: %.cpp 
    $(CXX) $(CXXFLAGS) $< -c -o $@

# recipe to build shared lib
libtest.so: version.o
    $(CXX) $(CXXFLAGS) $^ -shared -o $@

# recipe to build the target executable
test: test.o libtest.so
    $(CXX) $(CXXFLAGS)  $< -L. -ltest  -o $@

# recipe to clean up after ourselves
clean:
    rm -f *.o test

我期望的符号在库中:

$ nm libtest.so | grep version
0000000000201027 D _binary_version_txt_end
0000000000000007 A _binary_version_txt_size
0000000000201020 D _binary_version_txt_start

但是,我从链接器收到此警告:

/usr/bin/ld: warning: type and size of dynamic symbol `_binary_version_txt_size' are not defined

在程序运行时,将打印错误的符号值:

$ LD_LIBRARY_PATH=$(pwd) ./test
Size: 0 <- expected 7

这是dlsymextern "C"的工作,还是指定-E链接器选项的工作?我有一些没有成功的事情。

谢谢!

解决方法

因此,我找到了“按我的方式”做事,但仍然认为洛林奇的方法更好。

我最终放弃了尝试读取字符串大小的想法,并提出了运行良好的代码:

#define DATASTRING(NAME)                                                 \
  []() -> std::string {                                                  \
    extern char _binary_##NAME##_txt_start[];                            \
    extern char _binary_##NAME##_txt_end[];                              \
    size_t sz = _binary_##NAME##_txt_end - _binary_##NAME##_txt_start; \
    std::string ans(_binary_##NAME##_txt_start,sz);                     \
    ans.pop_back();                                                      \
    return ans;                                                          \
  }()

用法示例

std::string version = DATASTRING(version);

我学到的其他东西:

  1. 至少在这种情况下,char[]char*不同。
  2. 链接到二进制文件的字符串不是以null终止的,您需要知道它们的大小或长度。