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

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

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

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

C#

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

Q&A

解決済

1回答

1376閲覧

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

you_design

総合スコア1

VC++

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

C#

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

0グッド

1クリップ

投稿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#への移行に詳しい方、ご教授ください。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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メソッドを呼んでいましたが、構造体だったのですね!!
guest

回答1

0

ベストアンサー

これでどうでしょう?unsafe を使わない方法です。

C#

1 [StructLayoutAttribute(LayoutKind.Sequential)] 2 public struct EthPacket 3 { 4 public byte data_type; 5 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 6 public byte[] timestamp; 7 } 8 9 [StructLayoutAttribute(LayoutKind.Explicit)] 10 public struct EthPacket1 11 { 12 [FieldOffset(0)] public EthPacket eth; 13 [FieldOffset(9)] public RawPoint raw; 14 } 15 16 [StructLayoutAttribute(LayoutKind.Explicit)] 17 public struct EthPacket2 18 { 19 [FieldOffset(0)] public EthPacket eth; 20 [FieldOffset(9)] public SpherPoint spher; 21 } 22 23 [StructLayoutAttribute(LayoutKind.Sequential)] 24 public struct RawPoint 25 { 26 public int x; 27 public int y; 28 public int z; 29 public byte reflectivity; 30 } 31 32 [StructLayoutAttribute(LayoutKind.Sequential)] 33 public struct SpherPoint 34 { 35 public uint depth; 36 public ushort theta; 37 public ushort phi; 38 public byte reflectivity; 39 } 40 41 public enum enumData 42 { 43 Raw, 44 Spher 45 } 46 47 void GetData(byte handle, IntPtr ptr, uint data_num, IntPtr client_data) { 48 if (ptr != IntPtr.Zero) { 49 EthPacket data = (EthPacket)Marshal.PtrToStructure(ptr, typeof(EthPacket)); 50 if (data.data_type == (byte)enumData.Raw) { 51 EthPacket1 data1 = (EthPacket1)Marshal.PtrToStructure(ptr, typeof(EthPacket1)); 52 RawPoint p_point_data = data1.raw; 53 } else if (data.data_type == (byte)enumData.Spher) { 54 EthPacket2 data2 = (EthPacket2)Marshal.PtrToStructure(ptr, typeof(EthPacket2)); 55 SpherPoint p_point_data = data2.spher; 56 } 57 } 58 } 59

投稿2022/05/07 07:04

編集2022/05/07 08:05
KOZ6.0

総合スコア2626

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

you_design

2022/05/07 09:17

ありがとうございます!! FieldOffsetで別けたところ、うまく取得できました。 他にも取得出来ていなかった箇所もありますので、参考にさせて頂きます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問