编辑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