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
ちなみにこのソースの状態だと、
form.textbox2.Textに0しか返ってきません。
しかも帰ってくるまでに異様に時間を喰っています…。
むむむ。
文字列は、ByValで渡してください。
(VB6であっても、VB.NETであっても同様です)
# VB6でByRef渡しすると、OLE STRING(BSTR)へのポインタとなるので、
# 「ポインタのポインタ」を渡しているようなイメージになってしまいます。
>魔界の仮面弁士さん
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
あ!変なところに一つ気付きました。
DLL側はvoidですよね?この場合。
ということはreturnは無いと言う事になって、
//DLL側
_declspec(dllexport) void _stdcall stringLen(int strlen,char* filename){
strlen = 0;
while (*filename != '\0'){
strlen++;
filename++;
}
}
って感じでしょうか?
しかし、未だ上手くいかないですねー。
そうじゃなくてdll側のstrlenがポインタ参照になってないので
値を返せないだけです。
int *strlenとしてVB側ではByRefで渡してやりましょう。
strlenは単純に数値だからポインタ参照にする必要ないんじゃない?
編集 削除VBに戻す必要があるんだからポインタじゃないとだめなんじゃない?
あとVBモジュール内のDLL宣言部が滅茶苦茶です。
VBでSingleで渡しているのにDLLでintで受けてたらまずいでしょ。
数値のやりとりをする場合…。
[Function の戻り値]
・DLL側→VBに数値を渡すために使用する。
[ByVal x As Longな引数]
・VB→DLLに数値を渡すために使用する。
[ByRef x As Longな引数]
・VB→DLL、DLL→VBと、相互に値を交換する事ができる。
・DLL側では、int*として処理する事になる。
VBに戻す場合に値渡しは可能だよ。
ポインタと混在した場合はよく分からないけど。
>皆様
いろんな情報ありがとうございます。
うーん、ちょっと混乱してきました。
>[Function の戻り値]
>・DLL側→VBに数値を渡すために使用する。
ここがキーポイントのようですね。
この場合、DLLのstrlenはint*にするのでしょうか?
少し検討する時間が必要みたいです。
この場合、DLLの戻り値じゃなくて引数のstrlenに値を返してるんだからDLLのstrlenはint *でしょう。
でVBのDLL宣言部は
Private Declare Sub stringLen Lib "stringlength.dll" (strlen As Long, ByVal filename As String)
です。
Cをやってたら簡単に分かると思ってたんだけどね。
以上の事を踏まえて、以下のようなソースにしてみましたが、
未だ帰ってくる値は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)のようにする方がよいのでしょうか??
皆様ありがとうございました!!
結局、
//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
で、できましたー!!
> _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を使えば良いだけですし。
>Dentalさん
まさにおっしゃる通りなんですが、
本当にやりたかったのは、DLLに文字列を渡して
きちんと渡されているかどうかを見ることだったのです。
きちんと渡っていることは確認できました。
_declspec(dllexport) void _stdcall stringLen(int* strlen,char* filename){
*strlen = 0;
while (*filename != '\0'){
strlen++;
filename++;
}
}
もう解決してしまってるけど
よく見てください
ポインタで渡してるんだから
strlen++じゃなくて(*strlen)++でしょ
なんか初歩的なミスが多いなぁ。。。
つかぬ事を伺うが、
_declspec(dllexport) int _stdcall stringLen(char* filename)は
(VB)filename文字列を
(DLL)filenameというポインタに渡しているということで良いのかな?
DLL側ではfilenameはポインタ扱い??