dポイントプレゼントキャンペーン実施中!

現在、C++/CLIプログラムをC#で使う必要があり、
C++/CLIで定義したメソッドとクラスでC#側とやり取りする必要が生じております。

以下の書き方で、C++/CLIとC#間のクラスのやり取りはできたのですが、
C++/CLI側で定義されているメソッド内で、ポインタが指し示す値(*id.head)が変わってしまいます(文字化けみたいな感じになる)。
引き渡したポインタ変数の値は一致しているのですが、
どうすれば、C++/CLI側で値を正しく取得できるのでしょうか?。


【C++/CLI側で定義されているクラス】
public value class class1
{
public :
ULONG code;
header    *head;
};
typedef struct _header
{
CHAR achCHdrType[2];
CHAR achMsgLen[2];
} header ;


【C++/CLI側で定義されているメソッド】
ULONG session::open(class1& id)
{
return session_oepn(id.code, *id.head)
}

【C#側でのメソッド参照】
class1 c1 = new class1();
uint status = session.open(&c1);


よろしくお願いします。

A 回答 (2件)

// C++/CLI側。



#include <cstdio>
#include <windows.h>

using namespace System;

namespace CppNative
{
struct SomeHeaderInfo
{
// なんで要素数が 2 なのか、この構造体で何がしたいのか、まったくもって不明。
char Type[2];
char MessageLength[2];
};

inline ULONG OpenDummySession(ULONG code, const SomeHeaderInfo& info)
{
for (int i = 0; i < 2; i++)
printf(__FUNCTION__ "(): Type[%d] = %d, MessageLength[%d] = %d\n",
i, static_cast<int>(info.Type[i]), i, static_cast<int>(info.MessageLength[i]));
return code;
}
}

namespace CppManaged
{
public value class SomeHeaderInfo
{
public:
char Type0;
char Type1;
char MessageLength0;
char MessageLength1;
};

public value class DataPack
{
public:
UInt32 Code;
SomeHeaderInfo Header;
};

public ref class Session
{
public:
static UInt32 Open(DataPack% dataPack)
{
CppNative::SomeHeaderInfo temp = {};
temp.Type[0] = dataPack.Header.Type0;
temp.Type[1] = dataPack.Header.Type1;
temp.MessageLength[0] = dataPack.Header.MessageLength0;
temp.MessageLength[1] = dataPack.Header.MessageLength1;
return CppNative::OpenDummySession(dataPack.Code, temp);
}
};
}

// C#側。

{
CppManaged.DataPack dataPack = new CppManaged.DataPack();
dataPack.Code = 128;
dataPack.Header.Type0 = 10;
dataPack.Header.Type1 = 20;
dataPack.Header.MessageLength0 = 110;
dataPack.Header.MessageLength1 = 120;
uint status = CppManaged.Session.Open(ref dataPack);
Console.WriteLine("Status = {0}", status);
}



C++/CLIは玄人向けの言語です。
悪いことは言わないので、怪我する前にネイティブC++とC#を基礎から勉強し直した方がいいです。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
すでに深手を負ってる感は否めないですねw。
ご指摘通り、基礎をもっと勉強します。。

もし、public value class DataPackにポインタ変数が含まれていた場合、C#側で正しい値を取得する方法はあるのでしょうか?

C#側でポインタを使うべきでないとは思うのですが、利用しなければいけないソフトが処理の結果をポインタで返して来るもので。

お礼日時:2011/02/23 11:11

異なる言語間では「引数の参照渡し」は出来ません。



参照する場所では「参照した先」が「別世界」なので、参照する時点では「参照すべき場所に、参照すべき内容のデータが存在しない」のです。

「参照渡し」と「ポインタ渡し」は、言語仕様上、ほぼ同じ動作を行いますから、混同している人が多いですが「実装レベルでは、まったく異なる記述」なので注意しましょう。

また「異なる言語での引数渡し」ですので、関数を参照している場所と、関数を定義している場所で「関数の呼び出し規約」も統一させなければなりません。

「関数の呼び出し規約」とは、例えば __stdcallとか__cdeclとかってマクロで定義してあるヤツです。

これが一致してないと、引数の積み込みと取り出しの実装が食い違ったり、引数をレジスタ渡ししているのにスタックから取り出そうとしたりと、色々と問題が起きます。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
異なる言語間で引数を渡すのは難しそうですね。

実際、値を受けわたす方法としては、「参照渡し」や「ポインタ渡し」などを使わずに、変数を一つ一つ渡す方がよいのでしょうか?
載せたコードでは省略しましたが、かなり量が多くて・・・。

お礼日時:2011/02/23 10:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!