簡體   English   中英

將值從struct分配給變量失敗

[英]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傳遞到消息框。 但是,這並沒有顯示出人們的期望。 NodeType的值仍然正確。 對於DOFValue ,顯示的值為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM