目标文件里有什么(链接、装载与库03)

目标文件里有什么

目标文件类型

windows按PE-COFF,linux按ELF

ELF文件分类

分段的好处

  1. 数据安全性
  2. 程序局部性
  3. 可重用性

ELF中的段

#查看目标文件结构和内容
objdump -h file

#查看目标文件代码段、数据段、BSS段大小
size file

#反汇编目标文件所有段
objdump -s -d file
#输出结果按  偏移量-十六进制机器码-汇编代码 格式

.text 代码段

.data 数据段,存放已初始化全局变量和静态变量

.rodata 只读数据段 存放const修饰的变量和字符串常量

.BSS 段 存放未初始化全局变量和静态变量

其他段:

注意以"."开头的段都是系统保留的段,应用程序可以使用非系统保留的名字作为段名

objcopy

Usage: objcopy [option(s)] in-file [out-file]
Copies a binary file, possibly transforming it in the process
The options are:

  • -I --input-target Assume input file is in format
  • -O --output-target Create an output file in format
  • -B --binary-architecture Set output arch, when input is arch-less
  • -F --target Set both input and output format to
  • ​ --debugging Convert debugging information, if possible
  • -p --preserve-dates Copy modified/access timestamps to the output
  • -D --enable-deterministic-archives
  • ​ Produce deterministic output when stripping archives (default)
  • -U --disable-deterministic-archives
  • ​ Disable -D behavior
  • -j --only-section Only copy section into the output
  • ​ --add-gnu-debuglink= Add section .gnu_debuglink linking to
  • -R --remove-section Remove section from the output
  • ​ --remove-relocations Remove relocations from section
  • -S --strip-all Remove all symbol and relocation information
  • -g --strip-debug Remove all debugging symbols & sections
  • ​ --strip-dwo Remove all DWO sections
  • ​ --strip-unneeded Remove all symbols not needed by relocations
  • -N --strip-symbol Do not copy symbol
  • ​ --strip-unneeded-symbol
  • ​ Do not copy symbol unless needed by
  • ​ relocations
  • ​ --only-keep-debug Strip everything but the debug information
  • ​ --extract-dwo Copy only DWO sections
  • ​ --extract-symbol Remove section contents but keep symbols
  • ​ --keep-section Do not strip section
  • -K --keep-symbol Do not strip symbol
  • ​ --keep-file-symbols Do not strip file symbol(s)
  • ​ --localize-hidden Turn all ELF hidden symbols into locals
  • -L --localize-symbol Force symbol to be marked as a local
  • ​ --globalize-symbol Force symbol to be marked as a global
  • -G --keep-global-symbol Localize all symbols except
  • -W --weaken-symbol Force symbol to be marked as a weak
  • ​ --weaken Force all global symbols to be marked as weak
  • -w --wildcard Permit wildcard in symbol comparison
  • -x --discard-all Remove all non-global symbols
  • -X --discard-locals Remove any compiler-generated symbols
  • -i --interleave[=] Only copy N out of every bytes
  • ​ --interleave-width Set N for --interleave
  • -b --byte Select byte in every interleaved block
  • ​ --gap-fill Fill gaps between sections with
  • ​ --pad-to Pad the last section up to address
  • ​ --set-start Set the start address to
  • ​ {–change-start|–adjust-start}
  • ​ Add to the start address
  • ​ {–change-addresses|–adjust-vma}
  • ​ Add to LMA, VMA and start addresses
  • ​ {–change-section-address|–adjust-section-vma} {=|+|-}
  • ​ Change LMA and VMA of section by
  • ​ --change-section-lma {=|+|-}
  • ​ Change the LMA of section by
  • ​ --change-section-vma {=|+|-}
  • ​ Change the VMA of section by
  • ​ {–[no-]change-warnings|–[no-]adjust-warnings}
  • ​ Warn if a named section does not exist
  • ​ --set-section-flags =
  • ​ Set section 's properties to
  • ​ --set-section-alignment =
  • ​ Set section 's alignment to bytes
  • ​ --add-section = Add section found in to output
  • ​ --update-section =
  • ​ Update contents of section with
  • ​ contents found in
  • ​ --dump-section = Dump the contents of section into
  • ​ --rename-section =[,] Rename section to
  • ​ --long-section-names {enable|disable|keep}
  • ​ Handle long section names in Coff objects.
  • ​ --change-leading-char Force output format’s leading character style
  • ​ --remove-leading-char Remove leading character from global symbols
  • ​ --reverse-bytes= Reverse bytes at a time, in output sections with content
  • ​ --redefine-sym = Redefine symbol name to
  • ​ --redefine-syms --redefine-sym for all symbol pairs
  • ​ listed in
  • ​ --srec-len Restrict the length of generated Srecords
  • ​ --srec-forceS3 Restrict the type of generated Srecords to S3
  • ​ --strip-symbols -N for all symbols listed in
  • ​ --strip-unneeded-symbols
  • ​ --strip-unneeded-symbol for all symbols listed
  • ​ in
  • ​ --keep-symbols -K for all symbols listed in
  • ​ --localize-symbols -L for all symbols listed in
  • ​ --globalize-symbols --globalize-symbol for all in
  • ​ --keep-global-symbols -G for all symbols listed in
  • ​ --weaken-symbols -W for all symbols listed in
  • ​ --add-symbol =[
    :][,] Add a symbol
  • ​ --alt-machine-code Use the target’s 'th alternative machine
  • ​ --writable-text Mark the output text as writable
  • ​ --readonly-text Make the output text write protected
  • ​ --pure Mark the output file as demand paged
  • ​ --impure Mark the output file as impure
  • ​ --prefix-symbols Add to start of every symbol name
  • ​ --prefix-sections Add to start of every section name
  • ​ --prefix-alloc-sections
  • ​ Add to start of every allocatable
  • ​ section name
  • ​ --file-alignment Set PE file alignment to
  • ​ --heap [,] Set PE reserve/commit heap to /
  • ​ --image-base
    Set PE image base to
  • ​ --section-alignment Set PE section alignment to
  • ​ --stack [,] Set PE reserve/commit stack to /
  • ​ --subsystem [:]
  • ​ Set PE subsystem to [& ]
  • ​ --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]
  • ​ Compress DWARF debug sections using zlib
  • ​ --decompress-debug-sections Decompress DWARF debug sections using zlib
  • ​ --elf-stt-common=[yes|no] Generate ELF common symbols with STT_COMMON
  • ​ type
  • ​ --verilog-data-width Specifies data width, in bytes, for verilog output
  • -M --merge-notes Remove redundant entries in note sections
  • ​ --no-merge-notes Do not attempt to remove redundant notes (default)
  • -v --verbose List all object files modified
  • @ Read options from
  • -V --version Display this program’s version number
  • -h --help Display this output
  • ​ --info List object formats & architectures supported
  • objcopy: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 srec symbolsrec verilog tekhex binary ihex plugin
  • Report bugs to http://www.sourceware.org/bugzilla/
图片格式转为二进制文件
objcopy -I binary  -O xxx -B xxx xxx.jpg  xxx.o

objdump

Usage: objdump <option(s)> <file(s)>
Display information from object <file(s)>.
At least one of the following switches must be given:

  • -a, --archive-headers Display archive header information
  • -f, --file-headers Display the contents of the overall file header
  • -p, --private-headers Display object format specific file header contents
  • -P, --private=OPT,OPT… Display object format specific contents
  • -h, --[section-]headers Display the contents of the section headers
  • -x, --all-headers Display the contents of all headers
  • -d, --disassemble Display assembler contents of executable sections
  • -D, --disassemble-all Display assembler contents of all sections
  • ​ --disassemble= Display assembler contents from
  • -S, --source Intermix source code with disassembly
  • ​ --source-comment[=] Prefix lines of source code with
  • -s, --full-contents Display the full contents of all sections requested
  • -g, --debugging Display debug information in object file
  • -e, --debugging-tags Display debug information using ctags style
  • -G, --stabs Display (in raw form) any STABS info in the file
  • -W[lLiaprmfFsoRtUuTgAckK] or
  • –dwarf[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
  • ​ =frames-interp,=str,=loc,=Ranges,=pubtypes,
  • ​ =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
  • ​ =addr,=cu_index,=links,=follow-links]
  • ​ Display DWARF info in the file
  • –ctf=SECTION Display CTF info from SECTION
  • -t, --syms Display the contents of the symbol table(s)
  • -T, --dynamic-syms Display the contents of the dynamic symbol table
  • -r, --reloc Display the relocation entries in the file
  • -R, --dynamic-reloc Display the dynamic relocation entries in the file
  • @ Read options from
  • -v, --version Display this program’s version number
  • -i, --info List object formats and architectures supported
  • -H, --help Display this information

The following switches are optional:
-b, --target=BFDNAME Specify the target object format as BFDNAME
-m, --architecture=MACHINE Specify the target architecture as MACHINE
-j, --section=NAME Only display information for section NAME
-M, --disassembler-options=OPT Pass text OPT on to the disassembler
-EB --endian=big Assume big endian format when disassembling
-EL --endian=little Assume little endian format when disassembling
–file-start-context Include context from start of file (with -S)
-I, --include=DIR Add DIR to search list for source files
-l, --line-numbers Include line numbers and filenames in output
-F, --file-offsets Include file offsets when displaying information
-C, --demangle[=STYLE] Decode mangled/processed symbol names
The STYLE, if specified, can be auto', gnu’,
lucid', arm’, hp', edg’, gnu-v3', java’
or `gnat’
–recurse-limit Enable a limit on recursion whilst demangling. [Default]
–no-recurse-limit Disable a limit on recursion whilst demangling
-w, --wide Format output for more than 80 columns
-z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling
–start-address=ADDR Only process data whose address is >= ADDR
–stop-address=ADDR Only process data whose address is < ADDR
–prefix-addresses Print complete address alongside disassembly
–[no-]show-raw-insn Display hex alongside symbolic disassembly
–insn-width=WIDTH Display WIDTH bytes on a single line for -d
–adjust-vma=OFFSET Add OFFSET to all displayed section addresses
–special-syms Include special symbols in symbol dumps
–inlines Print all inlines for source line (with -l)
–prefix=PREFIX Add PREFIX to absolute paths for -S
–prefix-strip=LEVEL Strip initial directory names for -S
–dwarf-depth=N Do not display DIEs at depth N or greater
–dwarf-start=N Display DIEs starting with N, at the same depth
or deeper
–dwarf-check Make additional dwarf internal consistency checks.
–ctf-parent=SECTION Use SECTION as the CTF parent
–visualize-jumps Visualize jumps by drawing ASCII art lines
–visualize-jumps=color Use colors in the ASCII art
–visualize-jumps=extended-color Use extended 8-bit color codes
–visualize-jumps=off Disable jump visualization

objdump: supported targets: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 srec symbolsrec verilog tekhex binary ihex plugin
objdump: supported architectures: i386 i386:x86-64 i386:x64-32 i8086 i386:intel i386:x86-64:intel i386:x64-32:intel i386:nacl i386:x86-64:nacl i386:x64-32:nacl iamcu iamcu:intel l1om l1om:intel k1om k1om:intel

The following i386/x86-64 specific disassembler options are supported for use
with the -M switch (multiple options should be separated by commas):
x86-64 Disassemble in 64bit mode
i386 Disassemble in 32bit mode
i8086 Disassemble in 16bit mode
att Display instruction in AT&T syntax
intel Display instruction in Intel syntax
att-mnemonic
Display instruction in AT&T mnemonic
intel-mnemonic
Display instruction in Intel mnemonic
addr64 Assume 64bit address size
addr32 Assume 32bit address size
addr16 Assume 16bit address size
data32 Assume 32bit data size
data16 Assume 16bit data size
suffix Always display instruction suffix in AT&T syntax
amd64 Display instruction in AMD64 ISA
intel64 Display instruction in Intel64 ISA
Report bugs to http://www.sourceware.org/bugzilla/.

自定义段

在函数或者全局变量前加入_attribute_((section(“name”)))属性就可以把相应的变量或函数放到以“name"作为段名的段中。

ELF文件结构

  • ELF文件头 描述整个文件基本属性,ELF文件版本、目标机器型号、程序入口地址等
  • ELF常用段
  • 段表 描述了ELF文件包含的所有段的信息,如段名、长度、在文件中的偏移、读写权限、及其他属性
文件头
#查看ELF文件头
readelf -h file

ELF的文件头中定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段的数量等。

ELF文件头结构及相关常数被定义在"/usr/include/elf.h"里

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;


typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf64_Half    e_type;                 /* Object file type */
  Elf64_Half    e_machine;              /* Architecture */
  Elf64_Word    e_version;              /* Object file version */
  Elf64_Addr    e_entry;                /* Entry point virtual address */
  Elf64_Off     e_phoff;                /* Program header table file offset */
  Elf64_Off     e_shoff;                /* Section header table file offset */
  Elf64_Word    e_flags;                /* Processor-specific flags */
  Elf64_Half    e_ehsize;               /* ELF header size in bytes */
  Elf64_Half    e_phentsize;            /* Program header table entry size */
  Elf64_Half    e_phnum;                /* Program header table entry count */
  Elf64_Half    e_shentsize;            /* Section header table entry size */
  Elf64_Half    e_shnum;                /* Section header table entry count */
  Elf64_Half    e_shstrndx;             /* Section header string table index */
} Elf64_Ehdr;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vfpBEDz5-1659779540707)(https://i.imgtg.com/2022/07/24/rngrD.png)]

文件类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TD2vG5en-1659779540708)(https://i.imgtg.com/2022/07/24/rnp36.png)]

机器类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UsBI6Jn3-1659779540709)(C:\Users\lujie\AppData\Roaming\Typora\typora-user-images\image-20220724155430386.png)]

段表
#读取段表
readelf -S file
typedef struct
{
  Elf32_Word    sh_name;                /* Section name (string tbl index) */
  Elf32_Word    sh_type;                /* Section type */
  Elf32_Word    sh_flags;               /* Section flags */
  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf32_Off     sh_offset;              /* Section file offset */
  Elf32_Word    sh_size;                /* Section size in bytes */
  Elf32_Word    sh_link;                /* Link to another section */
  Elf32_Word    sh_info;                /* Additional section information */
  Elf32_Word    sh_addralign;           /* Section alignment */
  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
} Elf32_Shdr;

typedef struct
{
  Elf64_Word    sh_name;                /* Section name (string tbl index) */
  Elf64_Word    sh_type;                /* Section type */
  Elf64_Xword   sh_flags;               /* Section flags */
  Elf64_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf64_Off     sh_offset;              /* Section file offset */
  Elf64_Xword   sh_size;                /* Section size in bytes */
  Elf64_Word    sh_link;                /* Link to another section */
  Elf64_Word    sh_info;                /* Additional section information */
  Elf64_Xword   sh_addralign;           /* Section alignment */
  Elf64_Xword   sh_entsize;             /* Entry size if section holds table */
} Elf64_Shdr;

段描述符数组第一个数组成员为NULL,后面每个段占一个位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYSjreyT-1659779540709)(https://i.imgtg.com/2022/07/24/rnR4b.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h3tt2lEo-1659779540710)(https://i.imgtg.com/2022/07/24/rnt2l.png)]

段类型

段标志位

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wTdzfaED-1659779540711)(https://i.imgtg.com/2022/07/24/rnLVs.png)]

系统保留段的属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ouXhDMDf-1659779540712)(https://i.imgtg.com/2022/07/24/rnQAa.png)]

段链接信息

重定位表

text段的重定位表.rel.text

data段的重定位表.rel.data

字符串表

字符串在ELF文件中都存在这个段,使用字符串在表中的偏移来引用字符串。

.strrab字符串表,用来保存普通的字符串,如符号的名字

.shstrtab段表字符串表,用来保存段表中用到的字符串,如段名

e_shstrndx表示段表字符串表在段表中的下标。

符号表

符号分类
  • 定义在本目标文件的全局符号,可以被其他目标文件引用
  • 本目标文件中引用的全局符号,却没有定义在本目标文件,叫外部符号,也叫符号引用
  • 段名,由编译器产生,值为该段的起始地址
  • 局部符号 只在编译单元内部可见。调试器可以使用这些符号来分析程序或核心转存文件。链接器忽略它们。
  • 行号信息
查看符号表
nm file
ELF符号表结构

.symtab段保存符号表。

typedef struct
{
  Elf32_Word    st_name;                /* Symbol name (string tbl index) */
  Elf32_Addr    st_value;               /* Symbol value */
  Elf32_Word    st_size;                /* Symbol size */
  unsigned char st_info;                /* Symbol type and binding */
  unsigned char st_other;               /* Symbol visibility */
  Elf32_Section st_shndx;               /* Section index */
} Elf32_Sym;

typedef struct
{
  Elf64_Word    st_name;                /* Symbol name (string tbl index) */
  unsigned char st_info;                /* Symbol type and binding */
  unsigned char st_other;               /* Symbol visibility */
  Elf64_Section st_shndx;               /* Section index */
  Elf64_Addr    st_value;               /* Symbol value */
  Elf64_Xword   st_size;                /* Symbol size */
} Elf64_Sym;

符号类型和绑定信息

符号所在段

符号值
  • 在目标文件中,如果是符号的定义并且该符号不是“COMMON块”类型的,则st_value表示该符号在段中的偏移。即符号所对应的函数或变量位于st_shndx指定的段,偏移st_value的位置。这是目标 文件中定义全局变量符号的最常见情况。
  • 在目标文件中,如果符号是"COMMON块"类型的,则st_value表示该符号的对齐属性。
  • 在可执行文件中,st_value表示符号的虚拟地址。
特殊符号
  • __executable_start,该符号为程序起始地址,不是入口地址,是程序的最开始的地址。
  • __etext或_etext或etext,该符号为代码段结束地址,即代码段最末尾的地址。
  • _edata或edata,该符号为数据段结束地址,即数据段最末尾的地址。
  • _end或end,该符号为程序结束地址

以上都是程序被装载时的虚拟地址

函数签名

c++函数签名转换工具,c++filt

extern “C”

因为c++和c的函数签名不一样,所以c++想要链接到c符号上,需要加上extern “C”,__cplusplus是c++编译器定义的宏

#ifdef __cplusplus
extern "C"{
#endif

#ifdef __cplusplus
}
#endif
弱符号与强符号

编译器默认函数和初始化了的全局变量为强符号,未初始化的全局变量为弱符号。

通过GCC的"__attribute__((weak))"来定义任何一个强符号为弱符号

强符号和弱符号是针对定义来说的,和引用无关

强符号
  • 不允许强符号被多次定义,不同的目标文件中不能有同名的强符号;如果存在多个强符号定义,则链接器被报符号重定义错误
  • 如果一个符号在某个目标文件中是强符号,在其他文件中都是弱符号,那么选强符号
  • 如果一个符号在所有目标文件中都是弱符号,那么选其中占用空间最大的一个 。
强引用

如果没有找到该符号的定义,链接器就会报符号未定义错误,这种被称为强引用

弱引用

在处理弱引用时,如果该符号有定义,则链接器将该符号的引用决议;如果未定义,则链接器对于该引用不会报错,默认设置为0或者其他特殊值,以便程序代码能够识别。

弱引用和弱符号主要用在库的链接过程

在GCC中,使用"__attribute__((weakref))"声明一个外部函数的引用为弱引用。

调试信息

ELF文件采用DWARF的标准调试信息格式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
文中是linuxC++动态 实现接口提供类导出的一个例子 注意其中使用函数返回基类指针的用法,因为Linux的动态链接不能像MFC中那样直接导出类 一、介绍 如何使用dlopen API动态地加载C++函数和类,是Unix C++程序员经常碰到的问题。 事实上,情况偶尔有些复杂,需要一些解释。这正是写这篇mini HOWTO的缘由。 理解这篇文档的前提是对C/C++语言中dlopen API有基本的了解。 这篇HOWTO的维护链接是: http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/ 二、问题所在 有时你想在运行时加载一个(并使用其中的函数),这在你为你的程序写一些插件或模块架构的时候经常发生。 在C语言中,加载一个轻而易举(调用dlopen、dlsym和dlclose就够了),但对C++来说,情况稍微复杂。 动态加载一个C++的困难一部分是因为C++的name mangling (译者注:也有人把它翻译为“名字毁坏”,我觉得还是不翻译好), 另一部分是因为dlopen API是用C语言实现的,因而没有提供一个合适的方式来装载类。 在解释如何装载C++之前,最好再详细了解一下name mangling。 我推荐您了解一下它,即使您对它不感兴趣。因为这有助于您理解问题是如何产生的,如何才能解决它们。 1. Name Mangling 在每个C++程序(或目标文件)中, 所有非静态(non-static)函数在二进制文件中都是以“符号(symbol)”形式出现的。 这些符号都是唯一的字符串,从而把各个函数在程序、目标文件中区分开来。 在C中,符号名正是函数名:strcpy函数的符号名就是“strcpy”,等等。 这可能是因为两个非静态函数的名字一定各不相同的缘故。 而C++允许重载(不同的函数有相同的名字但不同的参数), 并且有很多C所没有的特性──比如类、成员函数、异常说明──几乎不可能直接用函数名作符号名。 为了解决这个问题,C++采用了所谓的name mangling。它把函数名和一些信息(如参数数量和大小)杂糅在一起, 改造成奇形怪状,只有编译器才懂的符号名。 例如,被mangle后的foo可能看起来像foo@4%6^,或者,符号名头甚至不包括“foo”。 其中一个问题是,C++标准(目前是[ISO14882])并没有定义名字必须如何被mangle, 所以每个编译器都按自己的方式来进行name mangling。 有些编译器甚至在不同版本间更换mangling算法(尤其是g++ 2.x和3.x)。 即使您搞清楚了您的编译器到底怎么进行mangling的,从而可以用dlsym调用函数了, 但可能仅仅限于您手头的这个编译器而已,而无法在下一版编译器下工作。 三、类 使用dlopen API的另一个问题是,它只支持加载函数。 但在C++中,您可能要用到中的一个类,而这需要创建该类的一个实例,这不容易做到。 四、解决方案 1. extern "C" C++有个特定的关键字用来声明采用C binding的函数: extern "C" 。 用 extern "C"声明的函数将使用函数名作符号名,就像C函数一样。 因此,只有非成员函数才能被声明为extern "C",并且不能被重载。 尽管限制多多,extern "C"函数还是非常有用,因为它们可以象C函数一样被dlopen动态加载。 冠以extern "C"限定符后,并不意味着函数中无法使用C++代码了, 相反,它仍然是一个完全的C++函数,可以使用任何C++特性和各种类型的参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

omnibots

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值