C代码调用template的函数

来个常规源码

[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);
}

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

猜你喜欢

转载自blog.csdn.net/rubikchen/article/details/121732958