質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

解決済

C++からC#への移行について、ポインタ→class変換できません。

you_design
you_design

総合スコア1

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

1回答

0評価

1クリップ

422閲覧

投稿2022/05/06 05:21

C言語で書かれているコードをC#で再現したいのですが、
C言語初心者の為に、教えてください。
開発環境は、VS2022
x64環境で出力したDLLを使用しています。

▽▽▽C言語側▽▽▽

typedef struct { uint8_t data_type; /**「RawPoint」or「SpherPoint」のType */ uint8_t timestamp[8]; uint8_t data[1]; /**< Point cloud data. */ } EthPacket ; typedef struct { int32_t x; int32_t y; int32_t z; uint8_t reflectivity; } RawPoint; typedef struct { uint32_t depth; uint16_t theta; uint16_t phi; uint8_t reflectivity; } SpherPoint; //デリゲートメソッド void GetData(uint8_t handle, EthPacket *data, uint32_t data_num, void *client_data) { if (data) { if(data ->data_type == enumData.Raw) { RawPoint *p_point_data = (RawPoint *)data->data; <-ここでは x y z reflectivityの値が入っている }else if ( data ->data_type == enumData.Spher) { SpherPoint *p_point_data = (SpherPoint *)data->data; } } }

▽▽▽C#側▽▽▽

[StructLayoutAttribute(LayoutKind.Sequential)] public class EthPacket { public byte data_type;    /**「RawPoint」or「SpherPoint」のType */    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] timestamp; public IntPtr data; /**< Point cloud data. */ } [StructLayoutAttribute(LayoutKind.Sequential)] public class RawPoint { public int x; public int y; public int z; public byte reflectivity; } [StructLayoutAttribute(LayoutKind.Sequential)] public class SpherPoint { public uint depth; public ushort theta; public ushort phi; public byte reflectivity; } void GetData(byte handle, IntPtr ptr, uint data_num, IntPtr client_data) { if (ptr != IntPtr.Zero) { EthPacket data = (EthPacket)Marshal.PtrToStructure(ptr, typeof(EthPacket)); GCHandle gch = GCHandle.Alloc(data.data, GCHandleType.Pinned); if (data.data_type == (byte)enumData.Raw) { RawPoint p_point_data = (RawPoint)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(RawPoint));  <-ここでは x y のみ値が入っている } else if (data.data_type == (byte)enumData.Spher { SpherPoint p_point_data = (SpherPoint)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(SpherPoint)); } gch.Free(); } }

RawPoint p_point_data = (RawPoint)Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(RawPoint));
でデータを確認すると、x , y のみ値が入っていますが、 Z , reflectivityのデータが0のままです。

ポインタからclassへの変換方法が間違っているのかが解からず困っています。
C++ C#への移行に詳しい方、ご教授ください。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

KOZ6.0

2022/05/06 09:26

なぜわざわざクラスにしているのでしょうか? クラスでなく、構造体を使えば、Marshal.PtrToStructure で事足りる気がします。
you_design

2022/05/06 12:40

KOZ6.0 さん ありがとうございます。 public class EthPacket → public struct EthPacket public class RawPoint → public struct RawPoint public class SpherPoint → public struct SpherPoint に変更しても結果は同じでした。。。 また、data.data = Intptr なので、 RawPoint p_point_data =(RawPoint)Marshal.PtrToStructure(data.data, typeof(RawPoint)); で良いのではと思いましたが、結果は 「System.AccessViolationException」とアクセスできませんでした。。 参照へのアクセス方法も異なるのでしょうか?
KOZ6.0

2022/05/06 19:22 編集

引数の ptr には EthPacket 構造体のアドレスが入っているのでしょうけど、どのように値をセットしているのでしょうか? また、C++ は 32bit 前提の構造体になっていますが 32bit でコンパイルする必要は無いのでしょうか?
you_design

2022/05/07 00:13

>引数の ptr には EthPacket 構造体のアドレスが入っているのでしょうけど、どのように値をセットしているのでしょうか? 値をセットいる箇所を見つけました。 一部、転記します。 void DataHandler::OnDataCallback(uint8_t handle, void *data, uint16_t size) { EthPacket *eth_data = (EthPacket *)data; if (eth_data == NULL) { return; } if (handle >= callbacks_.size()) { return; } DataCallback cb = callbacks_[handle]; switch (eth_data->data_type) { case kRaw: size = (size - kPrefixDataSize) / sizeof(RawPoint); break; case kSpherical: size = (size - kPrefixDataSize) / sizeof(SpherPoint); break; default: return; } if (cb) { cb(handle, eth_data, size, client_data_[handle]); ←ここでC#側に通知k } } void DataHandlerImpl::OnData(socket_t sock, void *client_data) { struct sockaddr addr; int addrlen = sizeof(addr); uint8_t handle = static_cast<uint8_t>(reinterpret_cast<uintptr_t>(client_data)); if (handle > data_buffers_.size()) { return; } std::unique_ptr<char[]> &buf = data_buffers_[handle]; if (buf.get() == NULL) { buf.reset(new char[kMaxBufferSize]); } int size = kMaxBufferSize; size = util::RecvFrom(sock, reinterpret_cast<char *>(buf.get()), kMaxBufferSize, 0, &addr, &addrlen); if (size <= 0) { return; } if (handler_) { handler_->OnDataCallback(handle, buf.get(), size); ←ここでCallBack } >また、C++ は 32bit 前提の構造体になっていますが 32bit でコンパイルする必要は無いのでしょうか? C++側は別の人が作ったのですが、64bit版しか無いようです。。 私に作成するノウハウがあれば良いのですが、C#側しか触ったことが無いために、C+側に手を入れる事が出来ておりません。。
KOZ6.0

2022/05/07 05:31

質問は編集できますので補足情報は質問側に記述してください。 C# のコードが出てくるものと思っていましたが、C++/CLR から C# の DLL を呼び出しているんですか? 肝心の EthPacket 構造体の data メンバをセットしている箇所が見当たりませんし、64ビットのアドレスを uint8_t で保持できるのか疑問です。
KOZ6.0

2022/05/07 06:27 編集

なんだか、unsafe を使ったほうがいいような気がしてきました。 「C#でポインタを使用する方法」 https://so-zou.jp/software/tech/programming/c-sharp/grammar/type/pointer/ EthPacket は、おそらく可変長で data メンバにアドレスが入っているのではなく、これ以降 RawPoint 構造体もしくは SpherPoint 構造体が入ってくるのかなと思います。
you_design

2022/05/07 09:12

>EthPacket は、おそらく可変長で data メンバにアドレスが入っているのではなく なるほど!! アドレスかと思いMarshal.PtrToStructureメソッドを呼んでいましたが、構造体だったのですね!!

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。