C代码调用template的函数

本文探讨了C++模板函数如何编译成实际函数,以及模板类的实例化过程。通过实例展示了如何用C代码调用类模板,并揭示了模板类与普通类的区别。重点讲解了模板在编译时的生成机制和模板类的运行时行为。

来个常规源码

[root@localhost design]# ./a.out
1
[root@localhost design]# cat dd.cpp
#include<iostream>
template <typename T>
void show(T a) {
    std::cout << a << std::endl;
}


int main(){
    show(1);
}

指令反编译一下

# objdump -d a.out

0000000000400814 <_Z4showIiEvT_>:
  400814:       55                      push   %rbp
  400815:       48 89 e5                mov    %rsp,%rbp
  400818:       48 83 ec 10             sub    $0x10,%rsp
  40081c:       89 7d fc                mov    %edi,-0x4(%rbp)
  40081f:       8b 45 fc                mov    -0x4(%rbp),%eax
  400822:       89 c6                   mov    %eax,%esi
  400824:       bf 60 10 60 00          mov    $0x601060,%edi
  400829:       e8 12 fe ff ff          callq  400640 <_ZNSolsEi@plt>
  40082e:       be b0 06 40 00          mov    $0x4006b0,%esi
  400833:       48 89 c7                mov    %rax,%rdi
  400836:       e8 65 fe ff ff          callq  4006a0 <_ZNSolsEPFRSoS_E@plt>
  40083b:       c9                      leaveq
  40083c:       c3                      retq
  40083d:       0f 1f 00                nopl   (%rax)

改改代码执行一下

[root@localhost design]# g++ dd.cpp -ldl -rdynamic
[root@localhost design]# ./a.out
1
1
[root@localhost design]# cat dd.cpp
#include<dlfcn.h>
#include<iostream>
template <typename T>
void show(T a) {
    std::cout << a << std::endl;
}


int main(){
    show(1);
    void(*td)(int);
    *(void**)&td = dlsym(RTLD_DEFAULT,"_Z4showIiEvT_");
    td(1);
}

最后成功用C代码调用类模板类。

模板类使用类才会生成代码。不适用这个模板就毫无意义,也就是实例化。
上面的C调用如果没有show(1)是执行不起来的。
模板在编译的时候会以上下文作为依据生成一个全局唯一函数,包括模板类也是这样。这就和CABI有点类似了。

总结就是,模板函数只是被编译器编译成了另类的函数而已。没什么大不了的。而模板类则是被编译器改成了另类的类,使用的时候才创建对应类的代码,这个类是新的类型哟。

多个实例就有多份代码,怎么去重?编译器负责去重。特别是大型项目中的不同的.o里面。


下面反过来用C实现一下模板

[root@localhost design]# g++ dd.cpp -std=c++11
[root@localhost design]# ./a.out
1
[root@localhost design]# cat dd.cpp
#include<iostream>
template <typename T>
void show(T a);
extern "C" void _Z4showIiEvT_(int a) {
    std::cout << a << std::endl;
}


int main(){
    show(1);
}

注意不同编译器的函数名加密规则可能不一样,所以这个代码不一定能在所有平台跑。不过形式上大同小异。掌握原理即可。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值