• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:PINVOKEで構造体配列をマーシャルする方法)

PINVOKEで構造体配列をマーシャルする方法

このQ&Aのポイント
  • C#からPINVOKEを介してCで作成したdll内の関数を呼び出す際、構造体の配列を引数として渡す方法について調査しています。
  • 現在試している方法ではうまくいっていないため、問題点を特定することができません。
  • 構造体の配列をメンバーに持つ構造体を使用してデータの受け渡しを試みていますが、可能性としてはIntPtrを使用して自分でマーシャリングする必要があるかもしれません。

質問者が選んだベストアンサー

  • ベストアンサー
  • osiete03
  • ベストアンサー率100% (1/1)
回答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

  • 構造体

    下記プログラムの2次元配列を構造体の配列に作り変え,構造体を利用して生年月日の項目を追加し,形式は日を除いたYYYY/MMで持ち,生年月日の入出力は,YYYY/MM形式で行い,西暦が数字4桁で,西暦と月の間に'/'があり,月が01~12の範囲の数字の2桁になっている7文字の入力のみ受け付け,正しく入力されるまでそれ以外は再入力させたい。あとdo-while文をつかっている箇所をwhile文に直したいです.自力でやったのですが,わかりませんでした. どのようにしたらよいか教えてください. お願いします. include <stdio.h> #define BUFFERSIZE 11 #define MAX_PERSON 10 #define MAX_CHARS 10 int main(void) { char name[10][BUFFERSIZE]; int c; int count = 0; int i; int j; for (i = 0; i < MAX_PERSON; i++) { printf("氏名入力 : "); j = 0; /* 氏名の1文字目が'0'なら入力を終了 */ if ((c= getchar()) == '0'){ break; } if (c == '\n') { /* 改行のみの入力は再入力 */ do { printf( "再入力\n" ); /*再入力*/ printf("氏名入力 : "); } while ((c = getchar()) == '\n'); } name[i][j++] = c; /*1文字目を格納*/ if (name[i][0] == '0') { break; } while ((c = getchar()) != '\n' && c != EOF) { if (j < BUFFERSIZE - 1) { name[i][j++] = c; } } name[i][j] = '\0'; count++; /* 実際に入力した人数を記録*/ printf("累計 : %d \n", count); } /* 氏名と生年月日を出力したいです */ for (i = 0; i < count; i++) { for (j = 0; j < MAX_CHARS; j++) { if (name[i][j] == '\0'){ break; } putchar(name[i][j]); } putchar('\n'); } return 0; }

  • 素数 再帰関数

    メイン #include<stdio.h> extern void count_primes(void); extern void print_primes(void); int max; int count; int primes[1000] int main(void) { printf("Uper limit: "); scanf("%d",&max); count_primes(); print_primes(); } 素数を求める(関数呼び出し) extern int nextprime(int n); extern int max; extern int count; extern int primes[]; void count_primes(void) { int i; count=0; for(i=2;i<=max;i=nextprime(i)){ primes[count++]=i; } リカーバシブ(次の素数) int nextprime[int n] { int i; for(;;){ n++; for(i=2;i*i<=n;i=nextprime(i)){ if(n%i==0) break; } if(i*i>n) break; } return n; } 素数プリント #include<stdio.h> extern int count; extern int primes[]; void print_primes(void) { int i for(i=0;i<count;i++){ if((i>0)&&(i%10==0) printf("\n"); printf(" %6d",primes[i]); } printf("\n素数の数 %d\n",count); } これら4つのモジュールで素数 nが求められますがアルゴリズム理解できません。この2つの関数のアルゴリズムについて、ご教授ください。め

  • C++でCの構造体をnewするとまずいのでしょうか?

    以下のようなCで書かれたヘッダがあったとして ---testc.h--- typedef struct __Test { int i; char c[30]; char* x; } Test; これを以下のようにnewして使うのは問題ないでしょうか? ---test.cpp--- extern "C" { #include test.h } int main(void) { Test* test = new Test(); test->i = 30; test->c[3] = 'a'; test->x = "aiueo"; return 0; }

  • ファイル入力のデータを構造体に入れる方法

    VB.net(XP:VS2008のみフルインストール)にて テキストファイルから入力したデータを構造体st_testに入れたいと考えているのですが、実現できません。 どなたか、お力添えをお願いします。 テキストファイルは、事前に構造体(st_test)に値を入れ、 単純にFileOpen→OutPutしています。 (","や" "などでメンバ毎に分割等はしておりません。) 構造体 ---------------------- Public Structure st_test <VBFixedArray(63), MarshalAs(UnmanagedType.ByValArray, SizeConst:=64)> _ Dim A() As Byte Dim B As Integer <VBFixedArray(7), MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _ Dim N() As Byte <VBFixedArray((7), (11)), MarshalAs(UnmanagedType.ByValArray, SizeConst:=(72))> _ Dim S(,) As Byte <VBFixedArray(11), MarshalAs(UnmanagedType.ByValArray, SizeConst:=12)> _ Dim U() As Integer End Structure ---------------------- 実現しようとしている個所 ---------------------- Dim t As String Dim temp(2) as st_test FileOpen(1, "test1.txt", OpenMode.Input) Input(FileNum, t) '''temp(0) = CType(CType(t, Object), st_test)...? temp(0) = CType(t, st_test) | FileOpen(1, "test2.txt", OpenMode.Input) Input(FileNum, t) temp(1) = CType(t, st_test) ---------------------- 上記の様に処理を行えば簡単にできるのかと安易な発想でいましたが、 CTypeの処理で'String'の値を'st_test'に変換できません。 旨のエラーになり、うまく実現することができません。 そもそもString型のデータをst_testにキャストすることが不可能なのでしょうか? それともただ、実現方法がカスなのでしょうか? 実際の構造体のサイズは4000Byteを超え(メンバ数も多いです。。。) 一つ一つ入力していくことが現実的に不可能なため ファイルよりInputすることしか思いついておりません。 test1.txtの中身を秀丸で開いてみました。 参考になれば・・・。 改行はなく、"福岡"の後等にそれぞれ空白があります。 -------------------------- 福岡 . A1 14 15 16 17 18 19 XX XX XX XX XX XX -------------------------- 宜しくお願いします。

  • C#で構造体配列

    C#で構造体配列の操作練習?をしているのですが using System; using System.Collections.Generic; using System.Text; namespace test1 { public struct Data { public string name; // 名前 public uint value; // 値 } class read { Data[] human = new Data[300]; public static string idSearch() { for (int i = 0; i < 300; i++) { if (test1.read.human[i].value == 25) return test1.read.human[i].name; } } } } だと エラー CS0120: 静的でないフィールド、メソッド、またはプロパティ 'test1.read.human' で、オブジェクト参照が必要です。 と言うエラーが出るのですが、どうしてでしょうか?

  • 構造体の動的メモリについて

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUM 10 /*生徒数*/ typedef struct data { int num; /*従業員番号*/ char name[16]; /*名前*/ int jap; /*国語の点数*/ int math; /*数学の点数*/ }data; int main(void) { data test[NUM]; /*生徒のデータ*/ FILE *fp; /*ファイル操作用*/ int i; /*配列インデックス*/ int count; /*データ分割用*/ char s[100]; /*データ読み込み用*/ char *token; /*データ分割用*/ char *data[6]; /*分割データ保存用*/ fp = fopen ("data1.txt","r");        for (i=0; i<NUM; i++){ fgets (s, sizeof(s), fp); /*dataファイルから1行読み込み*/ token = strtok(s, ","); /*読み込んだデータを","で分割する*/ count=0; while (token != NULL){ data[count] = token; /*分割したデータを配列へ入れる*/ token = strtok(NULL,","); count++; } test[i].num = atoi(data[0]);       strcpy (test[i].name, data[1]); test[i].jap = atoi(data[2]); test[i].math = atoi(data[3]); } fclose(fp);       } このプログラムを構造体へのポインタの配列で管理するように変えたいのですが、どのように変更すればいいのでしょうか。 条件として、個人データを格納するメモリ領域とポインタの配列のメモリ領域は動的に確保します。 初心者でよくわからないので詳しく教えていただけると助かります。よろしくお願いします。

  • ポインタを使って構造体の配列を戻り値にするには

    関数の戻り値を構造体の配列(アドレスを受け渡しを利用して)にしたいのですがうまくゆきません。 以下のプログラムではコンパイルはできるのですが、 a0 = 2 a1 = 4198512 a2 = 4329332 と表示されてしまいa1,a2がうまくゆきません。 ********************************************* #include<stdio.h> struct test{ int a; }; struct test *func(void); void main(void) { struct test *data;//構造体ポインタ int i; data = func(); //ポインタにtest関数の戻り値(アドレス)を代入 for(i=0;i<=2;i++){   printf("a%d = %d\n",i,(data+i)->a); //構造体要素を表示 } } struct test *func(void) { struct test data[3]={1,2,3}; //構造体配列を定義 return (&data[0]); //構造体配列の先頭アドレスを返す } ************************************************* test関数から受ける取ったアドレス(&data[0])をポインタ(data)に代入して1づつずらして表示させれば a0=1,a1=2,a=3 となると思ったのですがどこが間違っているのでしょうか? よろしくお願いします。

  • 構造体配列とポインタについて

    いつもお世話になっています。 皆様には、本当にお世話になっています。 先日、皆様にアドバイスをいただいたのですが、私の勉強不足で結局・・・並び替えて表示できなかったです。 大変申し訳ないのですが、どこがダメなのか教えてください。 /********************/ /*--- 英単語辞書 ---*/ /********************/ #include <stdio.h> #include <string.h> #define NUMBER 50 /*登録数*/ #define MAX_NAME 20 /*単語の最大文字数*/ #define MAX_WAYAKU 30 /*和訳の最大文字数*/ /************************/ /*--- 単語帳の構造体 ---*/ /************************/ typedef struct { char name[MAX_NAME]; /*単語*/ char wayaku[MAX_WAYAKU]; /*和訳*/ }words; /***********************************************/ /*----- 単語の交換 -----*/ /***********************************************/ void swaps(words x, words y) { words temp = x; temp = x; x = y; y = temp; } /************************************************/ /*------ 単語と和訳の登録 ------*/ /* 関数tourokuword()は引数words tango[]の、イン*/ /*クリメントしたtango_counの順番に格納する。  */ /************************************************/ void tourokuword(words tango[], int tango_count) { char word[MAX_NAME]; /*単語の名前*/ char wa[MAX_WAYAKU]; /*単語の和訳*/ int i = 0; int j; printf("[単語]:"); scanf("%s", word); /*単語を単語帳に登録*/ strcpy(tango[tango_count].name, word); printf("[和訳]:"); scanf("%s", wa); /*和訳を単語帳に登録*/ strcpy(tango[tango_count].wayaku, wa); for( i = 0; i < tango_count; i++){ if(strcmp(tango[tango_count].name, tango[i].name) > 0){ swaps(tango[tango_count], tango[i]); } } } /***********************************************/ /*----- 登録された単語を表示する -----*/ /* 関数printword()は引数words tango[]の、イン */ /*クリメントしたtango_counの並び替えて表示する */ /***********************************************/ void printword(words tango[], int tango_count) { int i = 0; puts("登録されている単語を表示します。\n"); for (i = 0 ; i < tango_count; i++) { printf("[単語]:%s\n", tango[i].name); /*単語の表示*/ printf("[和訳]:%s\n", tango[i].wayaku); /*和訳の表示*/ } } /****************/ /*--- メイン ---*/ /****************/ int main(void) { words tangochou[NUMBER]; /*単語帳に50件登録*/ int menu_num; /*メニュー番号*/ int slct_num; /*選択番号*/ int tango_count = 0; /*登録数のカウント*/ while(1){ /****************************/ /*--- メニュー番号の入力 ---*/ /****************************/ do { printf("1・・・登録. 2・・・表示. 3・・・終了.\n"); printf("メニュー番号を入力してください。:"); scanf("%d", &menu_num); /*メニュ番号の入力*/ if (menu_num > 0){ break; } }while(menu_num != 0); /*メニュ番号が該当しない時は再入力*/ switch (menu_num){ case 1 :/*--- メニュー 1:単語と和訳の登録 ---*/ while(1) { if (tango_count < NUMBER){ printf("英単語と和訳を入力してください。:\n"); /*単語と和訳の登録*/ tourokuword(tangochou, tango_count); tango_count++; }else { puts("50件以上です。\n"); return 0; /*50件以上は終了する*/ } /*登録を続けるか?*/ printf("続けますか【Yes・・・1/No…0】:"); scanf("%d", &slct_num); if(slct_num != 1){ /*0なら終了。1なら継続。*/ break; } } break; case 2 :/*--- メニュー 2:登録された単語と和訳の表示 ---*/ printword(tangochou, tango_count); /*単語と和訳の表示*/ break; case 3 :/*--- メニュー 3:終了 ---*/ puts("終了します。\n"); return (0); default:/*--- メニュー 4:非メニュー番号の処理 ---*/ puts("メニュー番号が間違っています。"); break; } } return (0); }

  • テーブル配列の中身、出力値

    お世話になっております。 C言語勉強中のものです。 一定のひもをランダムに切断し、その長さを測ろうと思っています。 前回アドバイスを頂き、ソートを使って書いてみたのですが、詰まる部分があったのでご指導いただきたいと思いました。 #include <stdlib.h> #include <string.h> #include <stdio.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))   int GetRandom(int min, int max);   int compare_int(const void* a, const void* b);   int compare_str(const void* a, const void* b); int main(void) {   int int_table[] = {GetRandom(0,10000)};   int i;   qsort( int_table, ARRAY_SIZE(int_table), sizeof(int), compare_int );   for( i = 0; i < ARRAY_SIZE(int_table); ++i ) {     printf("%d\n",int_table[i] ); }   return 0; } int compare_int(const void* a, const void* b) {   return ( *(int*)a - *(int*)b ); } int GetRandom(int min, int max) {     return min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 【困っている箇所】 ・int int_table[]={} の中身に次のようなものを入れることで、ランダムに切ったひもを、ソートできると考えているのですが、その方法を色々ためしましたが上手くいきませんでした。このようなやり方で良いのか、その場合どのようにしたら良いか、また違うのかを教えていただきたいです。 for(i=0;i<10;i++) { printf("%d\n",GetRandom(0,10000)); } ・また最終的にソートしたものを比較させようと思っています。 「出力値を保存する方法」が分からないので教えて頂きたいです。 ----前回ご覧になってくださった方へ---- アドバイスありがとうございました。 まだ初心者ですが、色々ご教授下さるとうれしい限りです。

  • 動的配列の受け渡しについて

    動的に定義した2次元配列を受け渡す方法がわからなくて困ってます。 配列に-1以外が入っている場合の行数を数えるプログラムを作成しています。 しかし、コンパイルすると下のエラーが出てコンパイルできません。 error:cannot convert 'long int **' to 'long int (*)[2] for argument '1' to 'long int count_line(long int (*)[2])' #include <stdio.h> long count_line(long arrau[][2]); int main(void){   long** test = new long* [100];   for(long num1=0 ; num1<100 ; num1++){     test[num1] = new long [2];   }   for(int i=0 ; i<100 ; i++){     test[i][0]=-1;     test[i][1]=-1;   }   for(int num2=0 ; num2<10 ; num2++){     test[num2][0]=1;     test[num2][1]=1;   }   int x=0;   x = count_line(test);   printf("x=%d\n",x); } long count_line(long array[][2]){   long count=0;   long end=0;   long roop=0;   while(end!=-1){     if(array[roop][1]!=-1){       count++;     }     end=array[roop][1];     roop++;   }   return(count); } どなたかお助けをー(T_T)