DLLに文字列を受け渡しして、文字数を返すには?

解決


.NETS  2004-11-19 17:29:40  No: 86786  IP: [192.*.*.*]

VB側でテキストボックスに入力した文字列をDLLに渡して
DLL側で文字数を解析し、再びVBに返したいのですが、
なかなかうまくいきません…。

文字列ということでポインタ(参照渡し?)がキーポイント
だということまでは分かったのですが…
以下のようなソースになってしまっています。

//DLL側
_declspec(dllexport) int _stdcall stringLen(int strlen,char* filename){
  strlen = 0;
  while (filename != '\0'){
    strlen++;
    filename++;
  }
  return(strlen);
}


'VB Module内
Private Declare Sub stringLen Lib "stringlength.dll" (ByVal strlen As Single, ByRef filename As String)
Public strlen As Single

Public Sub getStrLen()
    Call stringLen(strlen, form.textbox.Text)  'textboxの文字列をDLLに渡す
    form.textbox2.Text = strlen      'textbox2に文字数を表示
End Sub

編集 削除
.NETS  2004-11-19 17:32:26  No: 86787  IP: [192.*.*.*]

ちなみにこのソースの状態だと、
form.textbox2.Textに0しか返ってきません。
しかも帰ってくるまでに異様に時間を喰っています…。
むむむ。

編集 削除
魔界の仮面弁士  2004-11-19 17:40:45  No: 86788  IP: [192.*.*.*]

文字列は、ByValで渡してください。
(VB6であっても、VB.NETであっても同様です)

# VB6でByRef渡しすると、OLE STRING(BSTR)へのポインタとなるので、
# 「ポインタのポインタ」を渡しているようなイメージになってしまいます。

編集 削除
.NETS  2004-11-19 17:48:37  No: 86789  IP: [192.*.*.*]

>魔界の仮面弁士さん

ByRefをByValに変えてみました。
ソースは以下のようになりましたが、
やはり帰ってくる数値は0のままです。謎です…。
因みに、帰ってくるまでの変な待ち時間は解消されましたー!。

//DLL側
_declspec(dllexport) int _stdcall stringLen(int strlen,char* filename){
    strlen = 0;
    while (*filename != '\0'){
        strlen++;
        filename++;
    }
    return(strlen);
}


'VB Module内
Private Declare Sub stringLen Lib "stringlength.dll" (ByVal strlen As Single, ByVal filename As String)
Public strlen As Single

Public Sub getStrLen()
    Call stringLen(strlen, form.textbox.Text)    'textboxの文字列をDLLに渡す
    form.textbox2.Text = strlen            'textbox2に文字数を表示
End Sub

編集 削除
.NETS  2004-11-19 17:54:56  No: 86790  IP: [192.*.*.*]

あ!変なところに一つ気付きました。
DLL側はvoidですよね?この場合。
ということはreturnは無いと言う事になって、
//DLL側
_declspec(dllexport) void _stdcall stringLen(int strlen,char* filename){
    strlen = 0;
    while (*filename != '\0'){
        strlen++;
        filename++;
    }
}
って感じでしょうか?

しかし、未だ上手くいかないですねー。

編集 削除
sasa  2004-11-19 18:22:53  No: 86791  IP: [192.*.*.*]

そうじゃなくてdll側のstrlenがポインタ参照になってないので
値を返せないだけです。
int *strlenとしてVB側ではByRefで渡してやりましょう。

編集 削除
夕タ  2004-11-19 18:28:01  No: 86792  IP: [192.*.*.*]

strlenは単純に数値だからポインタ参照にする必要ないんじゃない?

編集 削除
sasa  2004-11-19 18:35:49  No: 86793  IP: [192.*.*.*]

VBに戻す必要があるんだからポインタじゃないとだめなんじゃない?
あとVBモジュール内のDLL宣言部が滅茶苦茶です。
VBでSingleで渡しているのにDLLでintで受けてたらまずいでしょ。

編集 削除
魔界の仮面弁士  2004-11-19 18:36:58  No: 86794  IP: [192.*.*.*]

数値のやりとりをする場合…。

[Function の戻り値]
・DLL側→VBに数値を渡すために使用する。

[ByVal x As Longな引数]
・VB→DLLに数値を渡すために使用する。

[ByRef x As Longな引数]
・VB→DLL、DLL→VBと、相互に値を交換する事ができる。
・DLL側では、int*として処理する事になる。

編集 削除
夕タ  2004-11-19 18:39:44  No: 86795  IP: [192.*.*.*]

VBに戻す場合に値渡しは可能だよ。
ポインタと混在した場合はよく分からないけど。

編集 削除
.NETS  2004-11-19 18:44:14  No: 86796  IP: [192.*.*.*]

>皆様

いろんな情報ありがとうございます。
うーん、ちょっと混乱してきました。

>[Function の戻り値]
>・DLL側→VBに数値を渡すために使用する。

ここがキーポイントのようですね。
この場合、DLLのstrlenはint*にするのでしょうか?

少し検討する時間が必要みたいです。

編集 削除
sasa  2004-11-19 18:48:37  No: 86797  IP: [192.*.*.*]

この場合、DLLの戻り値じゃなくて引数のstrlenに値を返してるんだからDLLのstrlenはint *でしょう。
でVBのDLL宣言部は
Private Declare Sub stringLen Lib "stringlength.dll" (strlen As Long, ByVal filename As String)
です。
Cをやってたら簡単に分かると思ってたんだけどね。

編集 削除
.NET  2004-11-19 18:59:45  No: 86798  IP: [192.*.*.*]

以上の事を踏まえて、以下のようなソースにしてみましたが、
未だ帰ってくる値は0のままです。

//DLL側
_declspec(dllexport) void _stdcall stringLen(int* strlen,char* filename){
    *strlen = 0;
    while (*filename != '\0'){
        strlen++;
        filename++;
    }
}

'VB側
Private Declare Sub stringLen Lib "stringlength.dll" (strlen As Long, ByVal filename As String)
Public Sub getStrLen()
    Call stringLen(strlen, form.textbox.Text)    'textboxの文字列をDLLに渡す
    form.textbox2.Text = strlen            'textbox2に文字数を表示
End Sub

DLL側の *strlen = 0 というのが気に懸かってますが…。
やはりreturn(strlen)のようにする方がよいのでしょうか??

編集 削除
.NETS  2004-11-19 19:13:11  No: 86799  IP: [192.*.*.*]

皆様ありがとうございました!!

結局、

//dll
_declspec(dllexport) int _stdcall stringLen(char* filename){
  int strlen = 0;
  while (*filename != '\0'){
    strlen++;
    filename++;
  }
  return(strlen);
}

'vb
Private Declare Function stringLen Lib "stringlength.dll" (ByVal filename As String) As Integer

Public Sub getStrLen()
    form.textbox2.Text = stringLen(form.textbox.Text)
End Sub

で、できましたー!!

編集 削除
Dental  2004-11-19 19:22:47  No: 86800  IP: [192.*.*.*]

> _declspec(dllexport) int _stdcall stringLen(char* filename){

> Private Declare Function stringLen Lib "stringlength.dll" (ByVal filename As String) As Integer

戻り値の場合、VB6なら As Long。VB.NETなら、As Integer ですね。


ところで、文字数を返すだけなら、DLLを使う必要は無いのでは?
VB6なら Len(Text1.Text)、VB.NETなら TextBox1.Text.Length で十分のような。
文字数ではなく、Shift_JIS換算のバイト数の意味だとしても、VB6なら
StrConv関数、VB.NETでは System.Text.Encodingを使えば良いだけですし。

編集 削除
.NETS  2004-11-19 21:00:29  No: 86801  IP: [192.*.*.*]

>Dentalさん

まさにおっしゃる通りなんですが、
本当にやりたかったのは、DLLに文字列を渡して
きちんと渡されているかどうかを見ることだったのです。

きちんと渡っていることは確認できました。

編集 削除
sasa  2004-11-19 21:29:51  No: 86802  IP: [192.*.*.*]

_declspec(dllexport) void _stdcall stringLen(int* strlen,char* filename){
    *strlen = 0;
    while (*filename != '\0'){
        strlen++;
        filename++;
    }
}
もう解決してしまってるけど
よく見てください
ポインタで渡してるんだから
strlen++じゃなくて(*strlen)++でしょ
なんか初歩的なミスが多いなぁ。。。

編集 削除
れんほ  2004-11-19 21:45:31  No: 86803  IP: [192.*.*.*]

つかぬ事を伺うが、
_declspec(dllexport) int _stdcall stringLen(char* filename)は

(VB)filename文字列を
(DLL)filenameというポインタに渡しているということで良いのかな?

DLL側ではfilenameはポインタ扱い??

編集 削除