編輯3描述調試分配值失敗
編輯4包含解決方案之後被縮小的問題 - 它是所有關於C和C#
我來到今天之間的類型差異橫跨一個奇怪的問題。在C,我有以下結構:
typedef struct s_z88i2
{
long Node;
long DOF;
long TypeFlag;
double CValue;
}s_z88i2;
而且我有一個功能(這是一個簡化版本):
DLLIMPORT int pass_i2(s_z88i2 inp, int total)
{
long nkn=0,ifg=0,iflag1=0;
double wert=0;
int val;
// Testplace 1
nkn=inp.Node;
ifg=inp.DOF;
iflag1=inp.TypeFlag;
wert=inp.CValue;
// Testplace 2
return 0;
}
分配的值無處使用 - 我知道這一點。 當我到達// Testplace 1
執行以下語句:
char tmpstr[256];
sprintf(tmpstr,"RB, Node#: %li, DOF#: %li, Type#: %li, Value: %f", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);
tmpstr
然後傳遞到一個消息。它顯示了 - 正如人們所期望的 - 我的結構中給出的值以一種很好和有序的方式傳遞給函數。通過函數繼續,結構中的值被分配給一些變量。在到達Testplace 2
以下被執行:
sprintf(tmpstr,"RB, Node#: %li, DOF#: %li, Type#: %li, Value: %f",nkn, ifg, iflag1, wert);
同樣,tmpstr
被傳遞到一個消息。但是,這並不能表明人們的期望。 Node
和Type
的值仍然正確。對於DOF
和Value
顯示的值是0
,這導致我得出結論:在分配值時出現了嚴重錯誤。我不知何故有時設法得到一個長數值的方法,這個數字與0
不一樣。但是我在最後的測試中無法再現這個錯誤。 inp
的可能值爲{2,1,1,-451.387}
,所以第一個1
和-451.387
被遺忘。
有誰知道我在做什麼錯或如何解決這個問題?
非常感謝提前!
編輯:
改變%i
到%li
但結果並沒有改變。謝謝放鬆!
我正在用Dev-Cpp使用MinGW開發這個dll(不幸),因爲我無法說服Visual Studio 2012 Pro正確編譯它。儘管原始資料的文檔說明它是純粹的ANSI-C。這有點讓我感到困惑,因爲我無法用Dev-Cpp正確調試這個dll。因此消息框。
編輯2:
作爲尼爾湯森建議的,我切換到經過參考。但是這也沒有解決問題。當我直接訪問結構中的值時,一切都很好。當我將它們分配給變量時,有些會丟失。
關於我如何調用函數的簡短通知。該DLL是從C#訪問的,所以我正在使用P/Invoke(正如我所瞭解的那樣)。
[DllImport("z88rDLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int pass_i2(ref s_z88i2 inp, int total);
是我在C#中的定義。我有很多其他功能導入,他們都很好。這是我第一次遇到這些問題的功能。我通過以下方式調用函數:
s_z88i2 tmpi2 = FilesZ88.z88i2F.ConstraintsList[i];
int res = SimulationsCom.pass_i2(ref tmpi2, FilesZ88.z88i2F.ConstraintsList.Count);
首先我設置結構,然後調用函數。
爲什麼哦爲什麼VS在編譯ANSI-C時挑剔?它肯定會讓事情變得更容易。
編輯3:
我可以到sprintf
縮小問題,我想。說服VS建立我的dll後,我能夠完成它。看起來這些值對於它們所屬的變量確實分配得非常好。但是,如果我想通過sprintf
打印這些變量,它們會變爲空(0
)。奇怪的是,價值總是0
而不是別的。我仍然對感興趣,爲什麼sprintf
表現這樣,但我認爲我的最初的問題解決/恐慌擊敗。所以謝謝大家!
編輯4:
正如下面supercat指出的,我有一個約C和C#之間類型兼容性反思。我知道在C#中的int
評估爲C中的long
。但經過仔細檢查,我發現在C中,我的變量實際上是FR_INT4
(爲了清晰起見,我保留原始問題=>壞主意)。內部FR_INT4
被定義爲:#define FR_INT4 long long
,所以爲超長久。一個快速測試表明,從C#中傳遞很長時間會提供最好的兼容性。因此,sprintf
組織可以簡化爲這樣一個問題:「長多長的格式標識符是什麼?」。
這實際上很簡單,它是%lli
。所以我可以公佈drumroll我的問題真的解決了!
sprintf(tmpstr,"RB, Node#: %lli, DOF#: %lli, Typ#: %lli, Wert: %f\n", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);
返回我想要的每個值。 非常感謝大家!
'long'在你的C代碼中代表什麼類型?在C#中,輸入'long'是一個64位整數,但在許多C實現中它是一個32位整數。 – supercat 2013-03-26 19:31:52
在我的C代碼中,我有很長的時間(實際上它是一個'FR_INT4',它是 - 通過編譯器標誌設置爲'#define FR_INT4 long long')從C#傳遞一個'int' - 這是我從這裏得到的 - 一旦傳遞給C,真的很久了。或者我錯了,'FR_INT4'真的很長,所以我應該從C#中傳出一段長時間? =>是的,我應該! (我會更新我的帖子,但再次;-)感謝您指點我! – lhiapgpeonk 2013-03-27 07:21:04
C#類型'long'是'System.Int64'的別名。我建議所有依賴內存佈局的代碼應該使用明確標識所涉及項目大小的類型,並且儘可能地嘗試按照其大小的倍數對齊所有具有二次大小的基元。避免使用位移4,12,20等字節的「double」或「Int64」項)。 – supercat 2013-03-27 16:17:30