- PR -

ネイティブコードのDLLへの参照渡しの方法(文字列型)

投稿者投稿内容
優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-09 19:25
いつもお世話になります。
優希です。

今回もまたDLL絡みなのですが、
もしかしたら自分の知識不足なのかもしれません。
何卒、アドバイスをお願い致します。


内容は、
ネイティブコードで作成されたDLLを呼び出すものです。
ただ単に呼び出すのは良いのですが、
VC++.Netにおける『参照渡し』の仕方について
お聞きしたいと思います。

# C#では分かりやすいし、
# 参考記事も多く見かけるんですが・・・。


呼び出されるDLLを"Sample.dll"としますと、
そのなかでは、以下のような
「渡した数値を、2つの形式の数値文字列に変換する関数」
があるとします。

コード:

///
/// 渡した数値を、2つの形式の数値文字列に変換する関数
///
///    [i]long NumValue		変換元の数値
///    [o]LPSTR data1		変換後の数値文字列1
///    [o]LPSTR data2		変換後の数値文字列1
///
NOMANGLE short CCONV GetData(long NumValue, LPSTR data1, LPSTR data2)
{
	// data1へ書き込み
	sprintf( data1, (const char *)"No.%02d", (unsigned char)NumValue);

	// data2へ書き込み
	sprintf( data2, (const char *)"No.%03d", (unsigned char)NumValue);
}




この関数をマネージドコード内で使用するとします。

コード:

	:
// 数値形式変換関数 (宣言)
[DllImport("Sample.dll")]
static int GetData(long NumValue, String *strData1, String *strData1);
 	:

///
/// 数値⇒数値文字列変換メソッド
///
void ChangeData()
{
 	:

	String *strData1;
	String *strData2;

	// 変換
	GetData(5, strData1, strData2);

 	:
	MessageBox::Show(String::Concat(S"strData1 = ", strData1));
	MessageBox::Show(String::Concat(S"strData2 = ", strData2));
}



ということをしたいのです。
(ある数値を、決まっている数値型文字列として、値を返す)



ここで、GetData()関数の第2引数、第3引数は、
『参照渡し』である必要があります。

が、MSDNの"Stringクラス"のサイトには
以下のように書いてあります。

引用:

String は、作成時点以降に値を変更できないことから、不変と呼ばれます。 String を変更するように見えるメソッドは、実際には変更内容が反映された新しい String を返します。文字列として使用されるオブジェクトの実際の内容を変更する必要がある場合には、 System.Text.StringBuilder クラスを使用してください。



実際にやってみてもそうなのですが、
値が取得できない状態です。

C#だと、refを使うと、
可能なのかと思うのですが・・。
(もしかしたら、出来ないかもしれないですけど(^^;))


何か有効な手段はありますでしょうか?
宜しくお願い致します。

# ちなみに、Sample.dllの内容は、
# 変更したくないので、呼び出し側で
# 対応できたら、、と思っています。
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-02-09 19:30
諸農です。

引用:

C#だと、refを使うと、
可能なのかと思うのですが・・。
(もしかしたら、出来ないかもしれないですけど(^^;))



直接の回答ではないです。

「ひらがなをカタカナに自動的に変換する。」のトピックで
C#を使ったWin32API呼び出しで、文字列の参照渡しのサンプルをアップしました。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=7712&forum=7
参考になればよいのですが。


_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-09 19:56
諸農さん、
ありがとうございます。

自分でも、
StringBuilderクラスを使用してみたのですが、
うまくいきませんでした。

その関数が呼ばれてたところで、
以降の処理が行なわれない状態になってしまいます。


ちなみに、下記のソースで、
引用:

int sz = ImmGetCompositionString(Imc,GCS_RESULTREADSTR,null,0);
StringBuilder str = new StringBuilder(sz);
ImmGetCompositionString(Imc,GCS_RESULTREADSTR,str,str.Capacity);


一度、nullを渡してその戻り値を、
StringBuilderクラスのインスタンス生成時に使用しているのは、
何か意味があるのでしょうか?

# 上記のようにやってみても、
# うまくいきませんでした。。。


優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-09 20:25
優希です。

VC++とVBでも
やり方は同じですよねぇ?

下記の記事も見て見ましたが・・・。
【Insider.NET 会議室】VC++の関数からVB.NETで文字列を受け取る方法


"LPSTR"型も
String型、またはStringBuilder型でいいはずなのですが・・・。


Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-02-09 20:52
諸農です。

引用:

一度、nullを渡してその戻り値を、
StringBuilderクラスのインスタンス生成時に使用しているのは、
何か意味があるのでしょうか?



え?えっとですね。。(^_^;
「参照渡し」で関数呼び出しするので、関数に渡すバッファを確保するための
必要なサイズを取得するためなんですが。。。。
#当たり前の回答で申し訳ない

で、ちなみに、nullに意味があるのではなく、
引き渡すサイズ用のパラメータに意味があるんです。

MSDNの「ImmGetCompositionString」の説明より引用
「バッファにコピーしたデータのバイト数が返ります。
dwBufLen パラメータに 0 を指定した場合は、要求し
た情報をすべて受け取るために必要となるバッファサイ
ズ( バイト単位)が返ります。エラーが発生すると、
次のいずれかのエラー値が返ります。」


_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
優希
ベテラン
会議室デビュー日: 2003/08/12
投稿数: 92
投稿日時: 2004-02-09 21:04
優希です。

引用:

え?えっとですね。。(^_^;
「参照渡し」で関数呼び出しするので、関数に渡すバッファを確保するための
必要なサイズを取得するためなんですが。。。。
#当たり前の回答で申し訳ない



そうなんですねー。
サイズ取得の為なんですね。
納得しました。


うーん。
Sample.dllのGetData()関数の引数で、
"LPSTR"型であったところを、"char *"型に
変えて呼び出して見たのですが、
同じような現象ですねぇ。

ですので、
明日、GetData()のどこでエラーになっているのか、
またはきちんと来ているのかを
検証してみる予定です。
Jubei
ぬし
会議室デビュー日: 2002/03/02
投稿数: 830
お住まい・勤務地: 関西
投稿日時: 2004-02-09 21:10
諸農です。

引用:

VC++とVBでも
やり方は同じですよねぇ?



Stringをアドレス渡ししてもダメなんですか?
もしくは__pinで固定してからアドレス渡しするとか・・
#試せていませんが(^_^;

_________________
諸農和岳
Powered by Turbo Delphi & Microsoft Visual Studio 2005

十兵衛@わんくま同盟
http://blogs.wankuma.com/jubei/
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2004-02-10 00:08
今簡単に実験してみましたけど、StringBuilderでいけましたよ。

--------- Sample.dll プロジェクト ------------
Sample.cpp
コード:


#include <windows.h>
#include <string.h>

void GetString(LPSTR lpStr) {
 char pChar[] = "abcdef";
 strcpy(lpStr, pChar);
}



export.def
コード:


LIBRARY Sample
EXPORTS
 GetString @1


----------------------------------------------

---------- test.exe プロジェクト -------------
コード:


#using <mscorlib.dll>
#using <System.dll>

using namespace System;
using namespace System::Runtime::InteropServices;
using namespace System::Text;

[DllImport("Sample.dll")]
void GetString(StringBuilder *sb);

int _tmain()
{
 StringBuilder *sb = new StringBuilder(10);
 GetString(sb);
 Console::WriteLine(sb->ToString());
 Console::Read();
 return 0;
}


----------------------------------------------

これで「abcdef」と表示されました。
それにしてもアップローダーがほしいですね…。

追記:単純な疑問ですが、MC++使うのならば普通にlibファイルやLoadLibraryでリンクすればいいように思うんですけど、なんか事情があるんですか?

[ メッセージ編集済み 編集者: ya 編集日時 2004-02-10 00:25 ]

スキルアップ/キャリアアップ(JOB@IT)