[英]Assigning value from struct to variable fails
編輯3描述了調試后縮小的范圍
編輯4包含解決方案-全部涉及C和C#之間的類型差異
今天我遇到一個奇怪的問題。 在CI中具有以下結構:
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
,這使我得出結論,在分配值期間出現了嚴重錯誤。 我有時不知何故設法獲得了一個長整數,因為值whis與0
一樣不正確。 但是在上一次測試中,我無法重現該錯誤。 的可能值inp
是例如{2,1,1,-451.387}
,所以第1
和-451.387
都忘了。
有人知道我在做什么錯或如何解決嗎?
提前謝謝了!
編輯:
將%i
更改為%li
但結果未更改。 謝謝放松!
我正在使用MinGW用Dev-Cpp開發此dll(不幸的是),因為我無法說服Visual Studio 2012 Pro正確地編譯它。 盡管原始資料的文檔說它是普通的ANSI-C。 這有點困擾我,因為我無法使用Dev-Cpp正確調試此dll。 因此,消息框。
編輯2:
正如尼爾·湯森(Neil Townsend)所建議的那樣,我轉而通過一個參考。 但這也沒有解決問題。 當我直接訪問結構中的值時,一切都很好。 當我將它們分配給變量時,會迷路。
關於我如何調用該函數的簡短通知。 該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);
首先,我設置結構,然后調用函數。
為什么?為什么在編譯ANSI-C時VS會變得挑剔? 這肯定會使事情變得容易。
編輯3:
我認為我可以將問題縮小到sprintf
。 說服VS構建我的dll后,我能夠逐步解決它。 看來,這些值確實確實非常好地分配給了它們所屬的變量。但是,如果我想通過sprintf
打印這些變量,它們的結果將是空的( 0
)。 奇怪的是,該值始終為0
而不是其他值。 我仍然對sprintf
為何采用這種方式感興趣,但我認為最初的問題已解決/恐慌失敗了。 所以,謝謝大家!
編輯4:
正如下面的超級貓指出的那樣,我對C和C#之間的類型兼容性有了重新思考。 我知道C#中的一個int
在C中的計算結果很long
。但是在FR_INT4
檢查之后,我發現在C中我的變量確實是FR_INT4
(出於清晰起見,我將其排除在原始問題之外,這是一個糟糕的主意)。 在內部將FR_INT4
定義為: #define FR_INT4 long long
,因此是super-long-long。 快速測試表明,從C#中經過很長時間才能獲得最佳兼容性。 因此,可以將sprintf
問題簡化為一個問題:“ long long的格式標識符是什么?”。
實際上,這是%lli
,非常簡單。 因此,我可以宣布鼓聲真的解決了!
sprintf(tmpstr,"RB, Node#: %lli, DOF#: %lli, Typ#: %lli, Wert: %f\n", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);
返回我想要的每個值。 非常感謝大家!
用格式說明符%i
格式化long
類型的值無效。 您應該使用%li
。
在C語言中,將引用或指針傳遞給結構而不是結構是一種更好的方法。 所以:
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;
}
您需要相應地更正sprintf行, inp.X
變為inp->X
要使用此功能之一:
// Option A - create it in a declaration, fill it, and send a pointer to that
struct s_z88i2 thing;
// fill out thing
// eg. thing.Node = 2;
pass_i2(&thing, TOTAL);
要么:
// Option B - create a pointer; create the memory for the struct, fill it, and send the pointer
struct s_z88i2 *thing;
thing = malloc(sizeof(struct s_z88i2));
// fill out thing
// eg thing->Node = 2;
pass_i2(thing, TOTAL);
這樣, pass_i2
將對您發送的結構進行操作,並且對它進行的任何更改都將在pass_i2
返回時pass_i2
。
為了澄清這個答案:
我的結構實際上是:
typedef struct s_z88i2
{
long long Node;
long long DOF;
long long TypeFlag;
double CValue;
}s_z88i2;
這需要long
才能從C#中傳遞(而不是我以前認為的int
)。 通過調試,我發現值的分配行為正常,問題出在sprintf
之內。 如果我將%lli
用作格式標識符,甚至可以解決此問題。
sprintf(tmpstr,"RB, Node#: %lli, DOF#: %lli, Typ#: %lli, Wert: %f\n", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);
是我需要使用的語句。 再次感謝所有貢獻者!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.