编辑 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
eg {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);
首先我设置结构,然后调用函数。
为什么哦 为什么VS在编译ANSI-C时要挑剔?它肯定会让事情变得更容易。
编辑3:
我认为,我可以将问题缩小到sprintf
。在说服 VS 构建我的 dll 之后,我能够逐步完成它。看来,这些值确实很好地分配给了它们所属的变量。但是,如果我想通过sprintf
它们打印这些变量,结果却是空的(0
)。奇怪的是,价值始终是0
而不是别的东西。我仍然对为什么会有 sprintf
这种行为感兴趣,但我认为我最初的问题已经解决/恐慌被打败了。所以谢谢大家!
编辑4:
正如 supercat 在下面指出的那样,我重新考虑了 C 和 C# 之间的类型兼容性。我知道int
C# 中的 a 评估为 C 中的 a long
。但是经过仔细检查后,我发现在 C 中我的变量确实是FR_INT4
(出于清晰的原因,我将其排除在原始问题之外=> 坏主意)。内部FR_INT4
定义为:#define FR_INT4 long long
,所以为超长-长。一个快速测试表明,从 C# 传递一个 long 可以提供最好的兼容性。所以sprintf
-issue 可以简化为问题:“long long 的格式标识符是什么?”。
实际上%lli
,这很简单。所以我可以宣布我的问题真的解决了!
sprintf(tmpstr,"RB, Node#: %lli, DOF#: %lli, Typ#: %lli, Wert: %f\n", inp.Node, inp.DOF, inp.TypeFlag, inp.CValue);
返回我想要的每个值。非常感谢大家!