2010-01-08 59 views
1

我無法從我寫的一些c代碼中取回字符串。通過interop接收字符串

首先是一些通常不相關的背景信息:我想從TAPI API接收用戶可讀的TAPI TSP字符串。我已經實施了一個半可行的TAPI解決方案,依靠匹配的驅動程序名稱來存儲字符串,但是想要改變這種方式來處理permanant行ID,因爲我們的客戶之一有一個拒絕以其他方式工作的(Alcatel)PBX 。

在C,我在我的頭文件中定義的功能爲:

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName); 

功能正是如此寫到:

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName) 
{ 
    //tapi code here... 

    //copy the string to DeviceName 
    wcscpy(DeviceName, (wchar_t*)((char *)devCaps + devCaps->dwLineNameOffset)); 
} 

如上所述,這最終會做一些有用的東西,但現在如果將abc放在我的wchar_t */StringBuilder中,並且可以在C#中看到,我會很高興。

在C#我定義該函數爲:

[DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)] 
    static extern void GetDeviceName(long DeviceId, StringBuilder DeviceName); 

我定義設備名稱作爲一個StringBuilder因爲字符串是immuatable和我想要的設備名稱,以C(This is recommended by MS)來設置。我還設置了返回類型爲void的渺茫希望,​​這也會影響某些內容(請參閱this半贊助性單文章以獲得部分僞科學解釋)。

,並呼籲它這樣:

StringBuilder name = new StringBuilder(); 
name.EnsureCapacity(100); 
long n = 0; 
GetDeviceName(n, name); 

我我的調試器附加到正在運行的進程,設置斷點,並通知在C代碼,不知怎的,StringBuilder的是變態的,並提供給非託管代碼作爲空指針。

AccessViolationException隨後在C#中拋出。

出了什麼問題?

刪除長參數有幫助。我可以在C中的DeviceName參數中添加「abc」,但是我想要這個長變量!我在做什麼錯誤或沮喪以便通過在那裏設置那個長參數來強制崩潰?

回答

1

在32位平臺上,long在.NET中爲8個字節(64位)寬,在本機代碼中爲4個字節(32位)。你需要改變你的P/Invoke方法是這樣的:

[DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)] 
static extern void GetDeviceName(int DeviceId, StringBuilder DeviceName); 

這樣,C#int和C long對32個平臺的寬度相同。

1

C++ long是32位,C#long是64位,不是嗎?因此,您需要使用int作爲第一個參數。

+0

沒有必要。 StringBuilder的是自動定義爲輸入,輸出] – 2010-01-08 11:05:05

+0

現在你已經走了,並通過編輯答案完全不同的東西迷惑大家,從而使我的意見無厘頭:) – 2010-01-08 14:30:31

+0

對此深感抱歉。但是每個人都看到它已經被編輯了,任何人都可以檢查歷史......;) – Lucero 2010-01-11 09:14:03

2

我想要變長但是

那麼你應該在C作爲long long定義參數。正如Lucero指出的那樣,C++中的長整型是32位,而C#中的長整型是64位。所以,如果你通過一個64位值,其中C函數需要一個32位的值,該函數讀取額外的32位作爲第二個參數,這顯然會導致一個錯誤的地址緩衝...