简体   繁体   English

将值从struct分配给变量失败

[英]Assigning value from struct to variable fails

Edit 3 describes the narrowed-down problem after debugging 编辑3描述了调试后缩小的范围

Edit 4 contains the solution - it's all about type difference between C and C# 编辑4包含解决方案-全部涉及C和C#之间的类型差异

Today I came across a curious problem. 今天我遇到一个奇怪的问题。 In CI have the following struct: 在CI中具有以下结构:

typedef struct s_z88i2
{
    long Node;
    long DOF;
    long TypeFlag;
    double CValue;

}s_z88i2;

Furthermore I have a function (this is a simplified version): 此外,我有一个功能(这是简化版):

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;
}

The assigned values are used nowhere - I'm aware of that. 分配的值无处使用-我知道。 When I reach // Testplace 1 the following statement is executed: 当我到达// 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 then is passed to a messagebox. 然后将tmpstr传递到消息框。 It shows - as one would expect - the values given in my struct I passed to the function in an nice and orderly way. 正如人们所期望的那样,它显示了我以良好且有序的方式传递给函数的结构体中给出的值。 Moving on through the function the values inside the struct get assigned to some variables. 通过该函数,将结构内部的值分配给某些变量。 On reaching Testplace 2 the following is executed: 到达Testplace 2后,将执行以下操作:

sprintf(tmpstr,"RB, Node#: %li, DOF#: %li, Type#: %li, Value: %f",nkn, ifg, iflag1, wert);

Again, tmpstr is passed to a messagebox. 同样, tmpstr传递到消息框。 However, this doesn't show what one would expect. 但是,这并没有显示出人们的期望。 The values for Node and Type are still correct. NodeType的值仍然正确。 For DOF and Value the displayed values are 0 which leads me to the conclusion that something is going terribly wrong during assigning the values. 对于DOFValue ,显示的值为0 ,这使我得出结论,在分配值期间出现了严重错误。 I somehow sometimes managed to get a way to long number for value whis was as incorrect as 0 . 我有时不知何故设法获得了一个长整数,因为值whis与0一样不正确。 But I have not been able to reproduce that mistake during my last tests. 但是在上一次测试中,我无法重现该错误。 Possible values for inp are eg {2,1,1,-451.387} , so the first 1 and -451.387 are forgotten. 的可能值inp是例如{2,1,1,-451.387} ,所以第1-451.387都忘了。

Does anyone know what I'm doing wrong or how to fix this? 有人知道我在做什么错或如何解决吗?

Many thanks in advance! 提前谢谢了!

Edit: 编辑:

Changed %i to %li but the result did not change. %i更改为%li但结果未更改。 Thank to unwind! 谢谢放松!

I'm developing this dll with Dev-Cpp using MinGW (unfortunately) because I wasn't able to convince Visual Studio 2012 Pro to compile this properly. 我正在使用MinGW用Dev-Cpp开发此dll(不幸的是),因为我无法说服Visual Studio 2012 Pro正确地编译它。 Although the documentation of the original source says it is plain ANSI-C. 尽管原始资料的文档说它是普通的ANSI-C。 This bugs me a bit because I cannot debug this dll properly with Dev-Cpp. 这有点困扰我,因为我无法使用Dev-Cpp正确调试此dll。 Hence the messageboxes. 因此,消息框。

Edit 2: 编辑2:

As Neil Townsend suggested, I switched to passing a reference. 正如尼尔·汤森(Neil Townsend)所建议的那样,我转而通过一个参考。 But this also did not cure the problem. 但这也没有解决问题。 When I access the values in my struct directly everything is fine. 当我直接访问结构中的值时,一切都很好。 When I assign them to variables some get lost. 当我将它们分配给变量时,会迷路。

A short notice on how I'm calling the function. 关于我如何调用该函数的简短通知。 The dll is to be accessed from C#, so I'm meddeling with P/Invoke (as I get it). 该dll是从C#访问的,所以我正与P / Invoke混在一起(据我所知)。

[DllImport("z88rDLL", CallingConvention = CallingConvention.Cdecl)]
public static extern int pass_i2(ref s_z88i2 inp, int total);

is my definition in C#. 是我在C#中的定义。 I have lots of other functions imported and they all work fine. 我还有很多其他导入的功能,它们都工作正常。 It is this function I encounter these Problems for the first time. 正是这个功能,我第一次遇到这些问题。 I call the function via: 我通过以下方式调用该函数:

s_z88i2 tmpi2 = FilesZ88.z88i2F.ConstraintsList[i];
int res = SimulationsCom.pass_i2(ref tmpi2, FilesZ88.z88i2F.ConstraintsList.Count);

First I set the struct, then I call the function. 首先,我设置结构,然后调用函数。

Why Oh Why has VS to be picky when it comes to compiling ANSI-C? 为什么?为什么在编译ANSI-C时VS会变得挑剔? It certainly would make things easier. 这肯定会使事情变得容易。

Edit 3: 编辑3:

I can narrow the problem down to sprintf , I think. 我认为我可以将问题缩小到sprintf Having convinced VS to build my dll I was able to step through it. 说服VS构建我的dll后,我能够逐步解决它。 It appears that the values are assigned very nicely indeed to the variables they belong in. If, however I want to print these variables via sprintf they turn out rather empty ( 0 ). 看来,这些值确实确实非常好地分配给了它们所属的变量。但是,如果我想通过sprintf打印这些变量,它们的结果将是空的( 0 )。 Curiously, that the value is always 0 and not something else. 奇怪的是,该值始终为0而不是其他值。 I'm still interested in why sprintf behaves that way, but I consider my initial problem solved/panic defeated. 我仍然对sprintf 为何采用这种方式感兴趣,但我认为最初的问题已解决/恐慌失败了。 So thanks everyone! 所以,谢谢大家!

Edit 4: 编辑4:

As supercat points out below, I had a rethink about type-compatibility between C and C#. 正如下面的超级猫指出的那样,我对C和C#之间的类型兼容性有了重新思考。 I was aware that an int in C# evaluates as a long in C. But after double-checking I found that in C my variables are really FR_INT4 (which I kept out of the original question for reasons of clarity => bad idea). 我知道C#中的一个int在C中的计算结果很long 。但是在FR_INT4检查之后,我发现在C中我的变量确实是FR_INT4 (出于清晰起见,我将其排除在原始问题之外,这是一个糟糕的主意)。 Internally FR_INT4 is defined as: #define FR_INT4 long long , so as a super-long-long. 在内部将FR_INT4定义为: #define FR_INT4 long long ,因此是super-long-long。 A quick test showed that passing a long from C# gives the best compatibility. 快速测试表明,从C#中经过很长时间才能获得最佳兼容性。 So the sprintf -issue can maybe be simplified to the question: "What is the format-identifier of a long long?". 因此,可以将sprintf问题简化为一个问题:“ long long的格式标识符是什么?”。

It is %lli which would is quite simple, actually. 实际上,这是%lli ,非常简单。 So I can announce drumroll that my problem really is solved! 因此,我可以宣布鼓声真的解决了!

sprintf(tmpstr,"RB, Node#: %lli, DOF#: %lli, Typ#: %lli, Wert: %f\n", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);

returns every value I want. 返回我想要的每个值。 Thank you very much everyone! 非常感谢大家!

Formatting a value of type long with the format specifier %i is not valid. 用格式说明符%i格式化long类型的值无效。 You should use %li . 您应该使用%li

In C, it is a better approach to pass a reference or pointer to the struct rather than the struct. 在C语言中,将引用或指针传递给结构而不是结构是一种更好的方法。 So: 所以:

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;
}

You will need to correct the sprintf liness accordingly, inp.X becomes inp->X . 您需要相应地更正sprintf行, inp.X变为inp->X To use this function either: 要使用此功能之一:

 // 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);

or: 要么:

 // 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);

This way pass_i2 will operate on the struct you send it, and any changes it makes will be there on return from pass_i2 . 这样, pass_i2将对您发送的结构进行操作,并且对它进行的任何更改都将在pass_i2返回时pass_i2

To clarify this as answered: 为了澄清这个答案:

My struct actually is: 我的结构实际上是:

typedef struct s_z88i2
{
    long long Node;
    long long DOF;
    long long TypeFlag;
    double CValue;
}s_z88i2;

which requires long to be passed from C# (and not int as I previously thought). 这需要long才能从C#中传递(而不是我以前认为的int )。 Through debugging I found out that the assignment of values behaves as it should, the problem was within sprintf . 通过调试,我发现值的分配行为正常,问题出在sprintf之内。 If I use %lli as format-identifier even this problem is solved. 如果我将%lli用作格式标识符,甚至可以解决此问题。

sprintf(tmpstr,"RB, Node#: %lli, DOF#: %lli, Typ#: %lli, Wert: %f\n", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);

Is the statement I need to use. 是我需要使用的语句。 So thanks again everyone who contributed! 再次感谢所有贡献者!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM