Cで作ったdll内の関数を.NET(C#)のプログラムからPINVOKEを介して呼び出そうとしているのですが、構造体の配列を引数として渡すにはどうするべきかわかりません。データの流れる向きは、両方向 [In, Out] です。下記の方法を試してうまくいかないのですが、どこが悪いのでしょうか?下記サンプルはうまくいかないのですが、構造体の配列をメンバーに持った構造体を使ってデータを受け渡そうとしています。もしかして、IntPtrを使って自分でマーシャリングしないとできませんか?
助言いただきたく、おねがいいたします。
-- 呼び出し側 --
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace MarshalTest
{
[StructLayout(LayoutKind.Sequential)]
class Data
{
private const int buffersize = 256;
[MarshalAs(UnmanagedType.I4)]
public int count;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = buffersize)]
public Byte[] data;
public Data()
{
count = 0;
data = new Byte[buffersize];
}
}
[StructLayout(LayoutKind.Sequential)]
class DataBundle
{
private const int buffersize = 8;
[MarshalAs(UnmanagedType.I4)]
public int count;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStruct, SizeConst = buffersize)]
public Data[] data;
public DataBundle()
{
count = 0;
data = new Data[buffersize];
for (int idx = 0; idx < buffersize; idx++)
{
data[idx] = new Data();
}
}
}
class Program
{
[DllImport("NativeDll.dll")]
private static extern void test1([Out] Data data);
[DllImport("NativeDll.dll")]
private static extern void test2([Out] DataBundle data);
static void Main(string[] args)
{
#if false
// これはできます。
Data data = new Data();
test1(data);
System.Console.WriteLine(Encoding.ASCII.GetString(data.data, 0, data.count));
#else
// これができません。
DataBundle data = new DataBundle();
test2(data);
for (int idx = 0; idx < data.count; idx++)
{
System.Console.WriteLine(Encoding.ASCII.GetString(data.data[idx].data, 0, data.data[idx].count));
}
#endif
}
}
}
-- 呼ばれ側 --
#include <Windows.h>
extern "C" {
#define MAX_DATA 256
#define MAX_BUNDLE 8
struct Data
{
int count;
char data[MAX_DATA];
};
struct DataBundle
{
int count;
Data data[MAX_BUNDLE];
};
__declspec(dllexport) void __stdcall test1(Data *data);
__declspec(dllexport) void __stdcall test2(DataBundle *data);
};
void __stdcall test1(Data *data)
{
const char *text = "osite !! goo !!";
data->count = strlen(text);
strcpy(data->data, text);
data->data[strlen(text)] = '\0';
}
void __stdcall test2(DataBundle *data)
{
const char *text = "osite !! goo !!";
for (int idx = 0; idx < MAX_BUNDLE; idx++)
{
strcpy(data->data[idx].data, text);
data->data[idx].data[strlen(text)] = '\0';
}
}
以上です。
No.1ベストアンサー
- 回答日時:
自分でマーシャリングすればできます。
-- 呼び出し側 --
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace MarshalTest
{
[StructLayout(LayoutKind.Sequential)]
class Data
{
private const int buffersize = 256;
[MarshalAs(UnmanagedType.I4)]
public int count;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = buffersize)]
public Byte[] data;
public Data()
{
count = 0;
data = new Byte[buffersize];
}
}
class Program
{
[DllImport("NativeDll.dll")]
private static extern void test3([In, Out] IntPtr data);
static void Main(string[] args)
{
Data[] data = new Data[4];
for (int idx = 0; idx < 4; idx++)
{
data[idx] = new Data();
}
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Data)) * 4);
IntPtr pos = new IntPtr(result.ToInt32());
for (int idx = 0; idx < 4; idx++)
{
Marshal.StructureToPtr(data[idx], pos, true);
pos = IntPtr.Add(pos, Marshal.SizeOf(typeof(Data)));
}
test3(result);
pos = new IntPtr(result.ToInt32());
for (int idx = 0; idx < 4; idx++)
{
data[idx] = (Data)Marshal.PtrToStructure(pos, typeof(Data));
pos = IntPtr.Add(pos, Marshal.SizeOf(typeof(Data)));
}
for (int idx = 0; idx < 4; idx++)
{
System.Console.WriteLine(Encoding.ASCII.GetString(data[idx].data, 0, data[idx].count));
}
Marshal.FreeHGlobal(result);
}
}
}
-- 呼ばれる側 --
#include <Windows.h>
extern "C" {
#define MAX_DATA 256
struct Data
{
int count;
char data[MAX_DATA];
};
__declspec(dllexport) void __stdcall test3(Data *data);
};
void __stdcall test3(Data *data)
{
const char *text = "osite !! goo !!";
for (int idx = 0; idx < 4; idx++)
{
strcpy(data[idx].data, text);
data[idx].data[strlen(text)] = '\0';
data[idx].count = strlen(text);
}
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- その他(プログラミング・Web制作) pythonでDBのカラム名で取得したオブジェクトの値を表示したい 1 2022/05/13 03:41
- JavaScript 【jquery】EasyUIのSubGridにMySQLのテーブルデータを表示&編集にしたい 5 2022/05/02 13:10
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- その他(プログラミング・Web制作) pandasでまとめてインデックスを削除するにはどうすればいいですか? たとえば、以下のプログラムで 1 2022/07/31 23:09
- C言語・C++・C# pythonのファイルの並びでの読み込みとリストについて 4 2022/04/13 03:52
- JavaScript EasyUIのSubGrid(jquery)におけるObjectに入れた連想配列について 1 2022/05/02 11:21
- その他(プログラミング・Web制作) Python - Excel で Webからデータを連続取得したいのですが エラーが出ます 1 2023/07/06 20:08
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ポインター引数の関数でコンパ...
-
stable diffusionのエラー
-
C言語でのLinuxとwindows共通の...
-
C言語の勉強しています。すみま...
-
printfの%eで指数部分の桁数を...
-
エクセルVBA:日付データの変換...
-
テキストファイルの結合について
-
PINVOKEで構造体配列をマーシャ...
-
パイプを用いたプロセス間通信...
-
reallocでうまくメモリを拡張出...
-
C言語
-
構造体のソートの方法について...
-
結城未来さんの年齢
-
C++/CLIのオブジェクト型配列
-
【Excel VBA】10進数を2進数に...
-
この花の名前を教えてください。
-
c言語での wavファイルの編集(...
-
H8/36064のAD変換データの文字...
-
「1TB」のHDDに日本語は何字入...
-
char str[256]の256の意味は?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ポインター引数の関数でコンパ...
-
stable diffusionのエラー
-
printfの%eで指数部分の桁数を...
-
エクセルVBA:日付データの変換...
-
linuxのシェルでファイル名に先...
-
int型(2バイト)データの分割
-
【Excel VBA】10進数を2進数に...
-
C#でのswitch文
-
データの値の近いものをグルー...
-
C言語 ファイル内のデータと入...
-
C言語の構造体にてバブルソート...
-
10個の実数に対する降順ソート...
-
'dataType' 引数を Null にする...
-
matlabのソースコードをpython...
-
c言語での wavファイルの編集(...
-
C言語の勉強しています。すみま...
-
テキストファイルの結合について
-
C言語についてです! 同じ年の...
-
Cのプログラムがどうしても動き...
-
matlabでのRRI検出
おすすめ情報