• 締切済み

C#からC言語で作成したDLLに文字列の配列の受け渡しをする方法を教えて下さい

初めまして、プログラミング自体経験が初心者なので根本的なところで間違っているかもしれませんがご指摘いただければと思いまして投稿します。 C#のプログラムからC言語で書かれたDLLを使いたいのですが、いくつか分からないことがあります。1つは文字列の配列の受け渡し方法、もう1つはその配列要素の文字列がマルチバイト文字である場合の方法です。 C#側 using System; using System.Runtime.InteropServices; public class MainClass { [DllImport("Cmdll.dll")] public static extern void SampleMethod([In, Out] string[] s, int x); static void Main() {     string[] str1 = new string[2] {"月曜日", "火曜日"};     SampleMethod(str1, n);     for (int i = 0; i < n; i++)       Console.WriteLine("str1[{0}] = {1}", i, str1[i]);   } } C言語側 void __declspec(dllexport) SampleMethod(char *str[], int n) {   int i;   for (i = 0; i < n; i++)     strcat(str[i], "ですね"); } なお、私用する文字を1バイト文字にすると動作しました。 DllImportの使い方も付け焼刃なので使い方が間違っていたらご指摘願えますでしょうか。よろしくお願いいたします。環境はVisual Studio 2008です。

みんなの回答

回答No.3

StringBuilder C# DLL で検索してみてください。 参考になるかどうかはわかりませんが、URL張っておきます。

参考URL:
www.atmarkit.co.jp/fdotnet/dotnettips/024w32api/w32api.html
phaz
質問者

お礼

情報ありがとうございます。 試してみます。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65535
  • ベストアンサー率43% (8533/19397)
回答No.2

追記。 >もう1つはその配列要素の文字列がマルチバイト文字である場合の方法です。 StringToHGlobalAnsiはネイティブな文字列を返す。 コンパイラの「文字セット」オプションを「UNICODE」にすればその文字列の中身はUNICODEとなるし「マルチバイト」にすればその文字列の中身はマルチバイトになる筈。 もちろん「メイン側」と「DLL側」は、文字セットオプションを同じにしてコンパイルしなければならない。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65535
  • ベストアンサー率43% (8533/19397)
回答No.1

>    string[] str1 = new string[2] {"月曜日", "火曜日"}; >    SampleMethod(str1, n); >void __declspec(dllexport) SampleMethod(char *str[], int n) { str1は「string[]」なのに、受け取り側で「char *[]」で受け取ろうとしてる。 「stringとchar *の違い」は「intとchar *の違い」と同じくらい違う。つまり「全然別物」って事だ。 -----     string[] str1 = new string[2] {"月曜日", "火曜日"};     char *chrstr[] = new char *[2];     for (int i = 0; i < n; i++)      //ネイティブな文字列を作る。結果はグローバルヒープに勝手に確保された領域へのポインタ      chrstr[i] = (char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str1[i]).ToPointer();     SampleMethod(chrstr, n);     for (int i = 0; i < n; i++)       Console.WriteLine("str1[{0}] = {1}", i, str1[i]);     //作られたネイティブな文字列はグローバルヒープに勝手に確保された領域なので、必ず解放する     for (int i = 0; i < n; i++)      System::Runtime::InteropServices::Marshal::FreeHGlobal(chrstr[i]);

phaz
質問者

補足

早速のお返事ありがとうございます。 str1は「string[]」なのに、受け取り側で「char *[]」で受け取ろうとしてることが問題なことは分かりました。ありがとうございます。しかし早速実際にやってみたのですが構文エラーと出てしまいます。 char *chrstr[] = new char *[2]; や chrstr[i] = (char*) System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str1[i]).ToPointer(); といった表現はC#で可能なのでしょうか。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 二次元配列による文字列の配列の受渡しについての質問です。

    二次元配列による文字列の配列の受渡しについての質問です。 #include <stdio.h> void print_pname(char str[][5], int n) { int i, j; for (i = 0; i < n; i++) { printf("str[%d] = \"", i); for (j = 0; str[i][j] != '\0'; j++) putchar(str[i][j]); printf("\"\n"); } } int main(void) { char ary[][5] = {"Lisp", "C", "Ada"}; print_pname(ary, sizeof(ary) / sizeof(ary[0])); return 0; } 上のプログラム中の関数print_pnameの引数char str[][5]についてですが char (*str)[5](配列のポインタ)と変更した場合にwarningが多数発生します。 これはどうしてでしょうか? また、上のプログラムを配列のポインタを使って変更することは可能でしょうか? 以上、よろしくお願いします。

  • C++DLLからC#へのコールバックに文字列の配列を渡したい

    教えてください! C++のアンマネージドDLLから、複数のファイル名(文字列)をC#に渡したいです。 ステップとしては、 C#から、C++のDLLの関数を最初に呼んで、コールバック関数を渡しています。 次に、DLLからコールバック関数を呼ぶ時に、複数のファイル名を渡したいです。 以下のコードを動かすと、、 C++からは2つ渡しているつもりなのに、 C#ではfilesがサイズ1のString配列として引数に入ってきます。 なぜでしょう? またどうすればC#から複数受け取れるでしょうか? 教えてください! C# public delegate int StringArrayCallback(String[] files); // C# -> C++ public static int start() { StringArrayCallback cb = new StringArrayCallback(onReceivedFiles); int ret = start(cb); return ret; } // C++ -> C# callback public static int onReceivedFiles(String[] files) { return 1; } C++コード typedef int (__stdcall *OnReceivedFilesProc )(char**); int start( OnReceivedFilesProc callback ) { std::string message1_ = "from C++1"; std::string message2_ = "from C++2"; char* messages_[2] = { (char*)message1_.c_str(), (char*)message2_.c_str() }; int ret_ = callback(messages_); std::cout << "[from c#]" << ret_; }

  • C言語 文字列の操作

    文字Cが含まれる個数を求めたいです #include <stdio.h> int str_chnum(const char str[],int c) { int i; int count=0; for(i=0;str[i]!="\0";i++) if (str[i]==c) count++; return(count); } int main(void) { char st[100]; printf("検索文字列を入力してください:"); scanf("%s",st) ; printf("検索文字列数は%uです。\n",st,int str_chnum(const str[],int c)); return(0); } コンパイルできません。なぜですか?printfの行がたぶん間違っていると思うんですが。。。

  • C言語:配列の中の文字を。。。

    こんにちは。 閲覧していただきありがとうございます。 長文になりますが勉強がわからず困っているので、ご助力いただけると助かります。 C言語についてです。 文字列の中に、特定の文字が出てきたときにだけ改行して表示するプログラムを作りたくて、以下のようにしてみました。(文字はアルファベット小文字のみです) #include<stdio.h> #include<string.h> int main(){  char str[200];  int i;  int k;  puts("文字列を入力");  gets(str);  k = strlen(str);  for(i=0;i<k;i++){    if(strcmp(str[i],"n")==0)     printf("\n");    printf("%c",str[i]);    }   return 0; } このプログラムにより期待する結果は、例えば入力した文字列が「abcdne abcn d」だとすれば、nが来たときに改行が実行されて abcd ne abc n d と表示されるようにしたいのですが、strcmpにintは渡せないとか、ポインタを使ってみても、実力不足ゆえに、「移植性のないポインタ変換」とかのエラーしか出ません。 どのようにすれば、この結果を得ることができるのでしょうか? ぜひご教授ください。よろしくお願いします。

  • C言語のint型の配列が分かりません

    #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名));  はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか?

  • C言語 配列 文字列

    配列と文字列をあわせて使う以下のようなプログラムを作りました.エラーはでないのですが,最後のprintfの部分が表示されません.どこが間違っているのでしょうか? /*文字列を入力し,入力した文字列を逆の順番で表示するプログラム*/ #include<stdio.h> #include<string.h> int main(void) { int i,n,t; char mozi[100]; printf("100字以下の文章を入力したら,逆にして表示します.\n"); gets(mozi); n=strlen(mozi); if(n%2) { for(i=0;i<(n-1)/2;i++) { t=mozi[i]; mozi[i]=mozi[n-i]; mozi[n-i]=t; } } else { for(i=0;i<n/2;i++) { t=mozi[i]; mozi[i]=mozi[n-i]; mozi[n-i]=t; } } printf(mozi); return 0; }

  • C言語の文字列の取り扱いが分かりません

    こんにちは。 C言語で分からないことがあり、質問させていただきました。 学校で、文字列の取り扱いを習いました。 そこで質問なんですが、以下のソースコードをstrcpy , strcat , strcmp , strlen を使わずに書くことってできないですか? 先生に質問したところ、ポインタとかいうのを使うのだそうですが、それを使わずに書くことってできるんですか?もしよろしければお願いします。 以下のプログラムですが、ユーザーから2つの文字列を受けて、そこから4つの文字列関数を使ってみましょう、というやつです。実行結果も貼っておきますね。 #include <string.h> #include <stdio.h> int main(void) { char str1[80], str2[80]; int i; printf("INPUT 1st word-line. : "); gets(str1); printf("INPUT 2nd word-line. : "); gets(str2); /*文字列(word-line)の長さを確認します。*/ printf("%s is %d moji long.\n", str1, strlen(str1)); printf("%s is %d moji long.\n", str2, strlen(str2)); /*文字列を比較します。*/ i = strcmp(str1, str2); if (!i) printf("two word-lines are same length.\n"); else if (i < 0) printf("%s is smaller than %s.\n", str1, str2); else printf("%s is bigger than %s.\n", str1, str2); /*十分なスペースがあるのなら、str2をstr1の最後に結合させます。*/ if((strlen(str1) + strlen(str2)) < 80 ){ strcat(str1, str2); printf("%s\n", str1); } /*str2をstr1にコピーする*/ strcpy(str1, str2); printf("%s %s\n", str1, str2);

  • Javaで配列を定義する方法

    こんにちは、片岡といいます。 Java言語で配列を定義する場合、以下の二つの書式に違いはありますか。 違いがあるとすれば、どのような違いですか。 また、違いがないのならば、どちらの記述がよいのですか。 ご存知の方はいらっしゃいませんか。 (1) public class Main1 { public static void main(String[] args) { String str[] = new String[] { new String("itiban"), new String("niban"), new String("sanban"), }; for (int i = 0; i < str.length; i++ ) { System.out.println(str[i]); } } } (2) public class Main2 { public static void main(String[] args) { String str[] = { new String("itiban"), new String("niban"), new String("sanban"), }; for (int i = 0; i < str.length; i++ ) { System.out.println(str[i]); } } } なお、私の環境は以下の通りです。 OS: Microsoft Windows XP Professional SP2 java: java version "1.4.2_13" 検索エンジンで"配列 オブジェクト java"を検索しましたが、 解決に役立つ情報は見つかりませんでした。

    • ベストアンサー
    • Java
  • c言語 文字列と配列

    #include<stdio.h> int charlen(int n); void cap2sml(int b); int main() { char a[100],b[100]; int n,i; /*Input CARACTERS*/ printf("CAPITAL?\n"); fgets(a,100,stdin); charlen(n); printf("total cahrs=%d\n",n); //printf in main cap2sml(i); printf("small=%s\n",b); return(0); int charlen(int n) n=0; while(1){ if(a[n]=='\0') break; n++; } void cap2sml(int b) int i; for(i=0;a[i]!='\0';i++){ b[i]=a[i]+0x20; } b[i]='\0' } のプログラムでエラーがでるのですが、どこを直せばよいでしょうか? ユーザー関数を使い文字列(大文字)を入力したときの文字列の長さと大文字を小文字に変化するプログラムです

  • C言語 文字列操作

    トリム関数とリムーブ関数を作成してみました。改良点はありますでしょうか? ~~~~以下ソース~~~~ #include <stdio.h> #include <stdlib.h> #include <string.h> char *Trim(char *str); char *Remove(char *str, char *rmv); void main(void) {  char str[10], rmv[10], *p;  int c;  /* " abcd "をトリムする */  strcpy(str, " abcd ");  printf("トリム前 |%s|\n", str);  p = Trim(str);  printf("トリム後 |%s|\n", str);  /* 指定文字列を削除する */  printf("削除する文字列を入力してください :");  scanf("%s", rmv);  Remove(str, rmv);  printf("削除後 |%s|\n", str);  exit(0); } char *Trim(char *str) {  char space[] = " ";  char null[] = "";  int index = 0;  while(1){   if(strcmp(&(str[index]), null) == 0){    index--;    if(strncmp(&(str[index]), space, 1) == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     break;    }   }else{    if(strncmp(&(str[index]), space, 1) == 0 && index == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     index++;    }   }  }  return str; } char *Remove(char *str, char *rmv) {  int c, size, i;  char *p;  c = '\0';  p = strchr(rmv, c);  size = p - rmv;  for(i = 0; i < size; i++){   c = (int)rmv[i];   p = strchr(str, c);   if (p != NULL) {    strcpy(&(str[p-str]), p + 1);   }   else{    printf("""%c""は見つかりませんでした\n", c);   }  }  return str; }