成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

C程序中讓兩個不同版本的庫共存

原文連接:http://blog.gotocoding.com/archives/875

讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名與空間、虛擬空間、營銷軟件、網(wǎng)站建設(shè)、鼓樓網(wǎng)站維護、網(wǎng)站推廣。

今天有同學提出,如何在一個C程序中讓兩個不同版本的庫共存。

首先想到的方案是,把其中一個版本的庫函數(shù)全部重命名,比如把每一個函數(shù)名都加一個_v2的后綴。

人工替換到?jīng)]什么,但是如果函數(shù)個數(shù)超過10個,就有點不拿人當人使了。

而使有工具去替換就會遇到一些棘手的問題,如何識別哪些是函數(shù),哪些是系統(tǒng)函數(shù)(系統(tǒng)函數(shù)不需要添加后綴)等。

隨后想到的另一個解決方案是C++的方案,為其中一個版本庫中的所有文件添加命名空間。然后使用g++將這部分代碼編譯成.o文件,之后再使用gcc將這些.o文件與整個程序中的其他代碼進行鏈接。

不過需要注意的是,g++編譯后所有導(dǎo)出接口名都會變化得不那么直觀。


第三種方案完全解決了以上兩種方案的痛點。

考慮一個C語言的編譯鏈接過程。

首先會將每個c文件編譯成.o文件。

在編譯過程中,導(dǎo)出函數(shù)并不會被實際分配地址,而是將函數(shù)名以F符號的方式存在.o文件的符號表中。

在本c文件調(diào)用的函數(shù)如果不存在于本文件,也會生成一個UND的符號存在.o文件的符號表中。

在鏈接過程中,鏈接器接收輸入的.o文件,為每個.o文件中的符號分存地址,并生成可執(zhí)行文件。

有了這幾點事實,問題就變得的簡單多了。

首先將其中一個版本的庫中所有代碼編譯為.o文件。然后收集所有.o文件中的F符號。

由于整個庫代碼有內(nèi)部依賴關(guān)系,收集到的F符號必然是所有.o文件中UND符號的超集。

換句話說,所有的F符號名就是我們要重命名的所有函數(shù)名。

這里我們需要借助objdump和objcopy工具。objdump -t 用于列表.o文件的符號表,objcopy用于重命名符號。

我隨手寫了一段用于過慮F符號的lua腳本

1
2
3
4
5
6
7
8
9
10
11
12
13
--rename.lua
local list = {}
local reg = "([^%s]+)%s+([^%s]+)%s+([^%s]+)"..
        "%s+([^%s]+)%s+([^%s]+)%s+([^%s]+)"
for l in io.stdin:lines() do
        local a,b,c,d,e,f = string.match(l, reg)
        if a and c == "F" then
                list[#list + 1] = " --redefine-sym "
                list[#list + 1] = string.format("%s=%s_v2", f, f)
        end
end
print("#/bin/sh")
print("objcopy " .. table.concat(list) .. " $1")

我們可以使用如下命令來收集所有.o文件的F符號, 并產(chǎn)生修改符號所用的腳本

1
find . -name '*.o' | xargs objdump -t | ./lua rename > rename.sh

現(xiàn)在我們只需要再執(zhí)行一條命令就可以把所有函數(shù)名增加一個_v2的后綴.

1
find . -name '*.o' | xargs -n 1 sh ./rename.sh

至此,我們這個版本的庫代碼的所有函數(shù)名已經(jīng)全部增加了_v2后綴。

這些被處理過的.o文件與我們將所有.c代碼中函數(shù)名重命名之后編譯出的.o文件完全一等價。


8月2號補充:

在實際使用中發(fā)現(xiàn), 局部函數(shù)(static 函數(shù))符號有可能會被gcc做修飾,將被修飾的符號重命名會給我們帶來一些麻煩,而我們原本也不需要去處理局部函數(shù)。

因此對rename.lua做如下修改,過慮掉非全局符號:

1
2
3
4
5
6
7
8
9
10
11
12
13
--rename.lua
local list = {}
local reg = "([^%s]+)%s+([^%s]+)%s+([^%s]+)"..
        "%s+([^%s]+)%s+([^%s]+)%s+([^%s]+)"
for l in io.stdin:lines() do
        local a,b,c,d,e,f = string.match(l, reg)
        if a and c == "F" and b == "g" then
                list[#list + 1] = " --redefine-sym "
                list[#list + 1] = string.format("%s=%s_v2", f, f)
        end
end
print("#/bin/sh")
print("objcopy " .. table.concat(list) .. " $1")

網(wǎng)站欄目:C程序中讓兩個不同版本的庫共存
轉(zhuǎn)載源于:http://jinyejixie.com/article46/iejeeg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App設(shè)計、Google、靜態(tài)網(wǎng)站網(wǎng)站制作、品牌網(wǎng)站建設(shè)、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站
个旧市| 黎城县| 竹山县| 怀宁县| 文登市| 睢宁县| 惠水县| 安龙县| 互助| 沙河市| 格尔木市| 桓仁| 绵阳市| 崇州市| 寿宁县| 朝阳县| 玉田县| 温泉县| 清丰县| 德化县| 榆社县| 东乡县| 朝阳市| 浦县| 七台河市| 营山县| 沁水县| 微山县| 清河县| 海晏县| 扎兰屯市| 石台县| 湛江市| 三都| 光山县| 克拉玛依市| 大田县| 虹口区| 陵川县| 银川市| 眉山市|