欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言代碼中調(diào)用C++代碼的方法示例

 更新時間:2017年02月03日 14:41:16   作者:WolfcsTech  
這篇文章主要介紹了C語言代碼中調(diào)用C++代碼的方法示例,文中也介紹了C++代碼調(diào)用C代碼的方法,有需要的朋友可以參考借鑒,下面來一起看看吧。

由于歷史原因,以及不同開發(fā)人員的技術(shù)偏好,C語言和C++語言都有一些獨有的非常有價值的項目,因而兩種語言的互操作,充分利用前人造的輪子是一件非常有價值的事情。

C++代碼調(diào)用C代碼很簡單,只要分別在包含的C頭文件的開頭和結(jié)尾加上如下的兩個塊:

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

即可。

然而為了支持類、重載等更加高級的特性,在編譯C++代碼時,C++符號會被修飾。我們dump Linux平臺加密庫 libcrypto++ 的符號表,可以看到如下的內(nèi)容:

$ readelf -s /usr/lib/libcrypto++.so
Symbol table '.dynsym' contains 9607 entries:
 Num: Value   Size Type Bind Vis  Ndx Name
  0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
  1: 00000000001daa58  0 SECTION LOCAL DEFAULT 9 
  2: 0000000000000000  0 OBJECT GLOBAL DEFAULT UND _ZTIi@CXXABI_1.3 (2)
  3: 0000000000000000  0 FUNC GLOBAL DEFAULT UND __errno_location@GLIBC_2.2.5 (3)
  4: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZSt18uncaught_exceptionv@GLIBCXX_3.4 (4)
  5: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZNSt8__detail15_List_node_base7_M_hookEPS0_@GLIBCXX_3.4.15 (5)
  6: 0000000000000000  0 FUNC GLOBAL DEFAULT UND getservbyname@GLIBC_2.2.5 (6)
  7: 0000000000000000  0 FUNC GLOBAL DEFAULT UND bind@GLIBC_2.2.5 (6)
  8: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZSt29_Rb_tree_insert_and_rebalancebPSt18_Rb_tree_node_baseS0_RS_@GLIBCXX_3.4 (4)
  9: 0000000000000000  0 FUNC GLOBAL DEFAULT UND __longjmp_chk@GLIBC_2.11 (7)
 10: 0000000000000000  0 OBJECT GLOBAL DEFAULT UND _ZTIh@CXXABI_1.3 (2)
 11: 0000000000000000  0 OBJECT GLOBAL DEFAULT UND _ZTVSt9basic_iosIcSt11char_traitsIcEE@GLIBCXX_3.4 (4)
 12: 0000000000000000  0 FUNC GLOBAL DEFAULT UND socket@GLIBC_2.2.5 (6)
 13: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZNSt14basic_ifstreamIcSt11char_traitsIcEED1Ev@GLIBCXX_3.4 (4)
 . . . . . .
 86: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZNSo5writeEPKcl@GLIBCXX_3.4 (4)
 87: 0000000000000000  0 FUNC GLOBAL DEFAULT UND malloc@GLIBC_2.2.5 (6)
 88: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZNSt9basic_iosIcSt11char_traitsIcEE4initEPSt15basic_streambufIcS1_E@GLIBCXX_3.4 (4)
 89: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZNSi5seekgElSt12_Ios_Seekdir@GLIBCXX_3.4 (4)
 90: 0000000000000000  0 FUNC GLOBAL DEFAULT UND pthread_key_delete@GLIBC_2.2.5 (3)
 91: 0000000000000000  0 FUNC GLOBAL DEFAULT UND shutdown@GLIBC_2.2.5 (6)
 92: 0000000000000000  0 FUNC GLOBAL DEFAULT UND _ZSt15set_new_handlerPFvvE@GLIBCXX_3.4 (4)
 93: 0000000000000000  0 FUNC GLOBAL DEFAULT UND pthread_getspecific@GLIBC_2.2.5 (3)
 94: 0000000000000000  0 FUNC GLOBAL DEFAULT UND strcmp@GLIBC_2.2.5 (6)
 95: 0000000000000000  0 FUNC GLOBAL DEFAULT UND strtol@GLIBC_2.2.5 (6)
 96: 0000000000000000  0 FUNC GLOBAL DEFAULT UND ioctl@GLIBC_2.2.5 (6)
 . . . . . .
 186: 00000000002c5a80 142 FUNC GLOBAL DEFAULT 12 _ZN8CryptoPP6xorbufEPhPKhS2_m
 187: 00000000002fd6d0  9 FUNC WEAK DEFAULT 12 _ZN8CryptoPP21InvertibleRSAFunction9BERDecodeERNS_22BufferedTransformationE
 188: 00000000001ea840 73 FUNC GLOBAL DEFAULT 12 _ZN8CryptoPP13Base64Decoder22GetDecodingLookupArrayEv
 189: 0000000000249760  6 FUNC WEAK DEFAULT 12 _ZThn8_N8CryptoPP13DL_SignerImplINS_25DL_SignatureSchemeOptionsINS_5DL_SSINS_13DL_Keys_ECDSAINS_4EC2NEEENS_18DL_Algorithm_ECDSAIS4_EENS_37DL_SignatureMessageEncodingMethod_DSAENS_6SHA256EiEES5_S7_S8_S9_EEED0Ev
 190: 0000000000278b60 86 FUNC WEAK DEFAULT 12 _ZN8CryptoPP8Rijndael3DecD1Ev
 191: 00000000001fd1f0  2 FUNC WEAK DEFAULT 12 _ZN8CryptoPP23DefaultEncryptorWithMAC8FirstPutEPKh
 192: 000000000026a490 51 FUNC GLOBAL DEFAULT 12 _ZN8CryptoPP23FilterWithBufferedInputC2EPNS_22BufferedTransformationE
 193: 0000000000285180  6 FUNC WEAK DEFAULT 12 _ZNK8CryptoPP8GCM_Base6IVSizeEv
 194: 000000000032e830 510 FUNC WEAK DEFAULT 12 _ZN8CryptoPP18StandardReallocateItNS_20AllocatorWithCleanupItLb0EEEEENT0_7pointerERS3_PT_NS3_9size_typeES8_b
 195: 00000000002a1790 185 FUNC WEAK DEFAULT 12 _ZSt18uninitialized_copyISt15_Deque_iteratorIyRKyPS1_ES0_IyRyPyEET0_T_S9_S8_
 196: 0000000000355610 25 OBJECT WEAK DEFAULT 14 _ZTSN8CryptoPP11RSAFunctionE
 . . . . . .

這與我們在源文件和頭文件里看到的那些函數(shù)、類的聲明定義都不一樣。通過binutils的工具c++filt demangle這些符號可以讓我們看到它們在代碼里的樣子:

$ c++filt _ZTSN8CryptoPP11RSAFunctionE
typeinfo name for CryptoPP::RSAFunction
$ c++filt _ZN8CryptoPP18StandardReallocateItNS_20AllocatorWithCleanupItLb0EEEEENT0_7pointerERS3_PT_NS3_9size_typeES8_b
CryptoPP::AllocatorWithCleanup<unsigned short, false>::pointer CryptoPP::StandardReallocate<unsigned short, CryptoPP::AllocatorWithCleanup<unsigned short, false> >(CryptoPP::AllocatorWithCleanup<unsigned short, false>&, unsigned short*, CryptoPP::AllocatorWithCleanup<unsigned short, false>::size_type, CryptoPP::AllocatorWithCleanup<unsigned short, false>::size_type, bool)

那到底有沒有辦法在C代碼中調(diào)用C++代碼呢?方法當(dāng)然是有的,而且還不止一種。

通過extern “C”調(diào)用

在 .cpp 文件中定義一個函數(shù),聲明為extern "C",則該函數(shù)可以方便地在C代碼中調(diào)用。由于該函數(shù)在 .cpp 文件中定義,因而在該函數(shù)的實現(xiàn)中,可以調(diào)用任意的C++代碼,包括C++函數(shù),創(chuàng)建C++類等等。

C++頭文件:

#ifndef CPPFUNCTIONS_H_
#define CPPFUNCTIONS_H_
#ifdef __cplusplus
int cpp_func(int input);
extern "C" {
#endif
int c_func(int input);
#ifdef __cplusplus
}
#endif
#endif /* CPPFUNCTIONS_H_ */

C++實現(xiàn)文件如下:

#include "CppFunctions.h"
int cpp_func(int input) {
 return 5;
}
int c_func(int input) {
 return cpp_func(input);
}

在C代碼里調(diào)用C++函數(shù):

#include <stdio.h>
#include "CppFunctions.h"
int main(int argc, char **argv) {
 printf("%d\n", c_func(10));
 return 0;
}

在C++文件里定義的c_func函數(shù)就像一座橋一樣,連接了C代碼的世界和C++代碼的世界。但 C 函數(shù)c_func的參數(shù)及返回值的類型自然是受到一定的限制的,但在函數(shù)實現(xiàn)中可以適配要調(diào)用的C++接口,做一些適配。

通過dlopen/dlsym調(diào)用

借助于在 .cpp 文件中定義的C函數(shù),間接地調(diào)用C++接口,固然是能實現(xiàn)在 C 代碼中調(diào)用C++代碼的目標(biāo),然而還是有些麻煩。通過libdl提供的接口,可以使我們的目標(biāo)通過更簡便的方式實現(xiàn)。

為dlsym傳入經(jīng)過修飾的符號,可以找到對應(yīng)的函數(shù)的地址。

通過如下命令將上面的CPPFunctions.cpp文件編譯為一個動態(tài)鏈接庫:

$ gcc -shared -fPIC CPPFunctions.cpp -o libCppLibTest.so

通過dlopen和dlsym找到對應(yīng)的C++函數(shù),并將其強制類型轉(zhuǎn)換為適當(dāng)類型的函數(shù)指針,然后通過函數(shù)指針調(diào)用目標(biāo)函數(shù),如:

#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char **argv) {
 void *libCPPTest = dlopen("/home/hanpfei0306/workspace_java/CppLibTest/Debug/libCppLibTest.so", RTLD_NOW);
 int (*cpp_func)(int) = (int (*)(int))dlsym(libCPPTest, "_Z8cpp_funci");
 printf("cpp_func = %p\n", cpp_func);
 printf("cpp_func output = %d\n", cpp_func(10));
 return 0;
}

編譯并執(zhí)行上面的代碼,在我的機器上可以看到如下的輸出:

cpp_func = 0x7f35727a8650
cpp_func output = 5

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • C++ CryptoPP使用AES實現(xiàn)加解密詳解

    C++ CryptoPP使用AES實現(xiàn)加解密詳解

    Crypto++ (CryptoPP) 是一個用于密碼學(xué)和加密的 C++ 庫,提供了大量的密碼學(xué)算法和功能,這篇文章主要為大家介紹了C++ CryptoPP如何使用AES實現(xiàn)加解密,需要的可以參考下
    2023-11-11
  • OpenCV實現(xiàn)直線檢測并消除

    OpenCV實現(xiàn)直線檢測并消除

    這篇文章主要為大家詳細介紹了OpenCV實現(xiàn)直線檢測并消除,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++ Explicit關(guān)鍵字詳細解析

    C++ Explicit關(guān)鍵字詳細解析

    以下是對C++中Explicit關(guān)鍵字的用法進行了詳細的介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-09-09
  • C++20 特性 協(xié)程 Coroutines(1)

    C++20 特性 協(xié)程 Coroutines(1)

    這篇文章主要給大家分享得是C++20 得特性 協(xié)程 Coroutines,下面文章內(nèi)容我們將來具體介紹什么是協(xié)程,協(xié)程得好處等知識點,需要的朋友可以參考一下
    2021-10-10
  • C語言中的字符型數(shù)據(jù)與ASCII碼表

    C語言中的字符型數(shù)據(jù)與ASCII碼表

    這篇文章主要介紹了C語言中的字符型數(shù)據(jù)與ASCII碼表,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • QT應(yīng)用啟動失敗排查方法小結(jié)

    QT應(yīng)用啟動失敗排查方法小結(jié)

    啟動QT應(yīng)用經(jīng)常會碰到應(yīng)用啟動失敗,qt platform plugin無法啟動,本文就來介紹一下QT應(yīng)用啟動失敗排查方法小結(jié),具有一定的參考價值,感興趣的可以了解以下
    2023-09-09
  • 深入了解C語言的動態(tài)內(nèi)存管理

    深入了解C語言的動態(tài)內(nèi)存管理

    所謂動態(tài)和靜態(tài)就是指內(nèi)存的分配方式。動態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存,本文將用5600字帶你深入了解動態(tài)內(nèi)存管理,感興趣的可以學(xué)習(xí)一下
    2022-07-07
  • C++深入刨析優(yōu)先級隊列priority_queue的使用

    C++深入刨析優(yōu)先級隊列priority_queue的使用

    最近我學(xué)習(xí)了C++中的STL庫中的優(yōu)先級隊列(priority_queue)容器適配器,對于優(yōu)先級隊列,我們不僅要會使用常用的函數(shù)接口,我們還有明白這些接口在其底層是如何實現(xiàn)的
    2022-08-08
  • C++實現(xiàn)LeetCode(34.在有序數(shù)組中查找元素的第一個和最后一個位置)

    C++實現(xiàn)LeetCode(34.在有序數(shù)組中查找元素的第一個和最后一個位置)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(34.在有序數(shù)組中查找元素的第一個和最后一個位置),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言JNI的動態(tài)注冊詳解

    C語言JNI的動態(tài)注冊詳解

    這篇文章主要介紹了JAVA JNI的動態(tài)注冊,這里提供簡單實例代碼,需要的朋友可以參考下,小編覺得寫的還不錯,希望能給你帶來幫助
    2021-08-08

最新評論