日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

『飞秋』在.NET 4中调用GDAL库时遇到的问题及解决方法

發(fā)布時(shí)間:2025/3/15 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 『飞秋』在.NET 4中调用GDAL库时遇到的问题及解决方法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

『飛秋』在.NET 4中調(diào)用GDAL庫(kù)時(shí)遇到的問(wèn)題及解決方法

最近需要在.NET 4的環(huán)境中調(diào)用GDAL庫(kù)。GDAL本身是一套非托管類(lèi)庫(kù),不過(guò)還好提供了用SWIG做的托管的Wrapper。

可以在FWTools的安裝包中找到這些Wrapper的編譯好的dll文件,不過(guò)FWTools中附帶的版本依賴(lài)于gdal_fw.dll(gdal_fw.dll是GDAL核心類(lèi)庫(kù)的修改版),而gdal_fw.dll依賴(lài)的其他非托管程序集太多了,加起來(lái)有18M左右。所以還是自己下載代碼編譯的好。

這篇文章介紹了1.4版本的下載和編譯方法,該方法同樣適用于現(xiàn)在最新的1.7版本。

編譯好之后引用、調(diào)用、Debug都沒(méi)問(wèn)題,一切正常,但是如果用Release編譯并在VS之外運(yùn)行的話(huà)則會(huì)報(bào)出AccessViolationException,異常信息提示說(shuō)訪(fǎng)問(wèn)了受保護(hù)的內(nèi)存。我的第一反應(yīng)就是托管的Wrapper中用P/Invoke調(diào)用了非托管程序集,而非托管程序集導(dǎo)致了這個(gè)問(wèn)題。但是這個(gè)猜測(cè)并不能解釋為什么只有在.NET 4+Release+IDE外運(yùn)行的情況下才會(huì)出錯(cuò)的現(xiàn)象。

猜來(lái)猜去,找來(lái)找去找到了問(wèn)題的所在:

GDAL的托管Wrapper中有一個(gè)叫做SWIGStringHelper的類(lèi)型,該類(lèi)型的靜態(tài)構(gòu)造方法中執(zhí)行了一些比較重要的初始化操作。另外一個(gè)叫做OsrPINVOKE的類(lèi)中聲明了一個(gè)SWIGStringHelper類(lèi)型的私有靜態(tài)字段,并在聲明時(shí)就new了該字段,而且OsrPINVOKE中沒(méi)有顯式聲明的靜態(tài)構(gòu)造。

把這兩個(gè)類(lèi)型的代碼簡(jiǎn)化一下的話(huà),大概是這樣的:


view sourceprint?01 class OsrPINVOKE?

02???? {?

03???????? private static SWIGStringHelper helper = newSWIGStringHelper();?

04????

05???????? public static void DoSomething()?

06???????? {?

07??????????? Console.WriteLine("static method of OsrPINVOKE");?

08???????? }?

09???? }?

10????

11???? class SWIGStringHelper?

12???? {?

13???????? static SWIGStringHelper()?

14???????? {?

15??????????? //這里做了一些重要的初始化?

16??????????? Console.WriteLine("SWIGStringHelper static constructor");?

17???????? }??????????????????????????????????????????

18 }


如果有代碼調(diào)用DoSomething,這段代碼執(zhí)行順序估計(jì)是這樣的:

OsrPINVOKE的靜態(tài)構(gòu)造方法(里面初始化helper這個(gè)靜態(tài)字段);

SWIGStringHelper的靜態(tài)構(gòu)造方法(輸出字符串);

SWIGStringHelper的實(shí)例構(gòu)造方法(里面啥也沒(méi)有做);

DoSomething方法(輸出字符串)。

所以應(yīng)該是先輸出SWIGStringHelperstatic constructor而后輸出static method ofOsrPINVOKE。

試著用下面的代碼調(diào)用一下:


view sourceprint?1 static void Main(string[] args)?

2???????? {?

3???????????? OsrPINVOKE.DoSomething();?

4???????????? Console.ReadLine();?

5???????? }


卻發(fā)現(xiàn)如果用的target framework是.net4,用release編譯并且在VS外運(yùn)行的話(huà),就會(huì)只輸出static method of OsrPINVOKE,感覺(jué)好像SWIGStringHelper的靜態(tài)構(gòu)造方法沒(méi)有執(zhí)行。而如果用的是.net 2.0、3.5,或者是用Debug編譯或是在VS里面運(yùn)行的話(huà)輸出結(jié)果都和預(yù)期的一致。

難道是靜態(tài)字段的初始化在.NET 4中變成Lazy的了?

事實(shí)證明真的是這樣:

如果一個(gè)類(lèi)型提供了顯式聲明的靜態(tài)構(gòu)造的話(huà),那么這個(gè)靜態(tài)構(gòu)造方法會(huì)在創(chuàng)建該類(lèi)型實(shí)例或者訪(fǎng)問(wèn)該類(lèi)型的任何靜態(tài)成員之前被執(zhí)行。

如果一個(gè)類(lèi)型沒(méi)有提供顯式聲明的靜態(tài)構(gòu)造的話(huà),編譯器會(huì)自動(dòng)給該類(lèi)型一個(gè)默認(rèn)的靜態(tài)構(gòu)造,并把靜態(tài)字段的初始化都放到該默認(rèn)靜態(tài)構(gòu)造中去,而這個(gè)默認(rèn)的靜態(tài)構(gòu)造只會(huì)在靜態(tài)字段被訪(fǎng)問(wèn)時(shí)才執(zhí)行,也就是說(shuō)創(chuàng)建實(shí)例、調(diào)用實(shí)例方法、調(diào)用靜態(tài)方法時(shí)都不會(huì)觸發(fā)靜態(tài)構(gòu)造的執(zhí)行(當(dāng)然前提是它們沒(méi)有訪(fǎng)問(wèn)靜態(tài)字段)。

不過(guò)CLR在加載一個(gè)類(lèi)型時(shí)怎么知道其中包含的靜態(tài)構(gòu)造方法是編譯器加上的還是原C#代碼中顯式提供的呢?事實(shí)上這是beforefieldinit的作用。

根據(jù)上面的原則再來(lái)分析一下:OsrPINVOKE中沒(méi)有顯式聲明的靜態(tài)構(gòu)造,所以編譯器會(huì)生成一個(gè)默認(rèn)的靜態(tài)構(gòu)造并把helper的實(shí)例創(chuàng)建放入其中。而這個(gè)默認(rèn)的靜態(tài)構(gòu)造只會(huì)在helper這個(gè)唯一的靜態(tài)字段被訪(fǎng)問(wèn)時(shí)才會(huì)執(zhí)行。而代碼中沒(méi)有任何地方訪(fǎng)問(wèn)了helper,所以O(shè)srPINVOKE的靜態(tài)構(gòu)造根本就沒(méi)有執(zhí)行,helper根本就沒(méi)有被new出來(lái),SWIGStringHelper的靜態(tài)構(gòu)造自然也就沒(méi)有執(zhí)行。

所以要解決這個(gè)問(wèn)題的話(huà)只要在OsrPINVOKE里面顯式聲明一個(gè)靜態(tài)構(gòu)造方法,把new SWIGStringHelper();這一句放到里面,或者僅僅是顯式聲明一個(gè)靜態(tài)構(gòu)造并把它留空。然后重新編譯一下GDAL的Wrapper就可以了。

如果您也在.NET 4中調(diào)用GDAL時(shí)遇到了類(lèi)似的問(wèn)題,不妨試一下這種解決方法。

其實(shí)不僅是GDAL,其他由SWIG制作的托管Wrapper估計(jì)都會(huì)受到影響。

參考:飛秋官網(wǎng):http://www.freeeim.com/

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的『飞秋』在.NET 4中调用GDAL库时遇到的问题及解决方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。