編集3は、デバッグ後の絞り込まれた問題について説明しています
Edit 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
たが、結果は変更されませんでした。くつろいでくれてありがとう!
Visual Studio 2012 Proにこれを適切にコンパイルするように説得できなかったため、(残念ながら)MinGWを使用してDev-Cppでこのdllを開発しています。元のソースのドキュメントには、それはプレーンな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#の間の型互換性について再考しました。int
in C#はin Cとして評価されることを知ってい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);
必要なすべての値を返します。みなさん、ありがとうございました!