dポイントプレゼントキャンペーン実施中!

/**** Cプログラム *****/
int testAP( char* a)
aのポインタにアドレスを返します。

/**** VB プログラム****/
Public Declare Function testAP Lib "test.dll" (ByRef a As String) As Integer


Dim keydata As String * 128

lngRc = testAP(keydata)

上記VBのAPを実行するとアプリケーションエラーになります。
Cプログラムのデバックをすると入口ではaのポインタにはアドレスがセットされていて
、値を設定出来、最後まで正常動作して、VBとのインタフェースで落ちています。
VB6.exeでアプリケーションエラーになっています。

恐らく、VBにはポインタという概念が無いと聞いていてCのAPとの受け渡しに失敗して
そうなのですが、VBでの引き渡し方法が分かりません。
よろしくお願い致します。

A 回答 (10件)

>__declspec(dllexport) int testAP(BSTR* cp_KeyData){


>
>→char*からBSTR*に変更しました。

だめです。そんな強引なことをしないでください。
char *でかまいません。
BSTR*にするとメモリ破壊が起きます。
__stdcallはどうしたんですか?
(ごめんなさい、アンダースコア2つですね)

>只、VCのデバックを行うと実行時エラー'49'
>DLLが正しく呼び出せません。が出力される。
>(DLL関数を呼んで処理が終了してVBに戻る所で出力されます。

VBのDeclareステートメントと、Cの処理があっていません。メモリを破壊しているのでしょう。
EXEにして動くのはたまたまでしょう。

この回答への補足

ご指導ありがとうございます。

__stdcallを試してみたのですが、実行時に
実行時エラー'453'
TestAPがDLLファイル C:\bin\test.dll内に見つかりません。
というエラーになってしまいます。

C側は
__declspec(dllexport) long __stdcall testAP(char*)

VB側は
Public Declare Function testAP Lib "c:\bin\test.dll" (ByVal lpKeyData As String)As Long

です。


test.dllはパス通りの場所には置いてあります。

なにか誤りがありましたらご指導お願い致します。

補足日時:2003/11/25 11:16
    • good
    • 0

モジュール定義ファイルはDLL作成時に作ってますか?


(ファイル名:test.def)
LIBRARY DLL名

EXPORTS
関数名1
関数名2
関数名3

こんな感じのファイルです。

参考URL:http://lion.zero.ad.jp/~zar70041/zarchis/archive …

この回答への補足

モジュール定義ファイルを作成したところ正常に動作しました。

皆様のご指導の結果、現状
VB側
Public Declare Function testAP Lib "C:\bin\test.dll" (ByVal lpKeyData As String) As Long
---------------------------------------------------------------------------
Dim lngRc As Long
Dim keydata As String * 128

keydata = String$(128, Chr(0) & Chr(0))
lngRc = testAP(keydata)



VC側
__declspec(dllexport) long __stdcall testAP(char *lpdata){
→C側でlpdataに値を設定する
}

モジュール定義
--- test.defファイル ----

LIBRARY test
EXPORTS
testAP


上記設定及びコンパイルで実行した結果
VB側でDLLのtestAPを呼び、正常に戻り、keydata変数には
C側で設定した値が返却されました。

VBからCのDLLを呼ぶ際は、モジュール定義ファイルも必要なのですね。
momoturboさん、hayahayahayaさん、taka_tetsuさん、sha-girlさん、FlossenEngelさん
ありがとうございました。皆様のおかげですごく助かりました。
また特にtaka_tetsuさん、sha-girlさんには大変時間をさいてもらって感謝しています。ありがとうございました。

補足日時:2003/11/25 14:26
    • good
    • 0

>エントリtestAPがDLLファイル内に見つかりませんと言うメッセージが出力されます。



#7の方の参考urlに書いてある、defファイルを作成してDLLのプロジェクトに追加してビルドしなおしてください。

この回答への補足

皆さんの意見を参考に下記の方法(但し、VBをコンパイル(EXE)にして)で
正しく処理が出来ました。!!

でも、下記の方法で大丈夫なのか不安です。
何かご指摘がありましたら、教えてください。
また、デバック時のエラーについて、知っている方がいれば教えてください。

/* ---- C側のプログラム ------*/

__declspec(dllexport) int testAP(BSTR* cp_KeyData){

→char*からBSTR*に変更しました。

char c_DATA[5]="1234"
LPSTR lp_DATA;

lp_DATA=(LPSTR)cp_KeyData;→LPSTRにアドレスをかぶせる

strcpy(lp_DATA,c_DATA);

return(OK);
}

/* ---- VB側のプログラム ------*/

Public Declare Function testAP Lib "test.dll" (ByVal lpKeyData As String) As Long

Dim lngRc As Integer
Dim keydata As String * 128→128Byte確保、確保しないとエラーとなってしまう?

lngRc = testAP(keydata)→keydataには"1234"が返されました。

/*****************************************************************************/
只、VCのデバックを行うと実行時エラー'49'
DLLが正しく呼び出せません。が出力される。
(DLL関数を呼んで処理が終了してVBに戻る所で出力されます。

VBをコンパイル(EXE)にして実行すると正しく処理が行われるます。

どうしてなのでしょう?

補足日時:2003/11/21 17:38
    • good
    • 0

参考までに↓(既に出ている回答以上の情報はありませんが)



参考URL:http://kamakura.cool.ne.jp/oppama/misc/dll.html
    • good
    • 1

>__declspec(dllexport) int FAR testAP(char* a)


>
>呼び出しは出来るのですが、aのアドレスがNULLです。

かも知れませんね。
呼び出しが出来るかどうかは関数がエクスポートされているかどうかだけです。
で、呼び出し規約は引数の渡し方の定義です。
ちなみに、FARはWin32では意味がありません。


>→ int _stdcall testAP(char* a)に修正した方が
>いいのでしょうか?

__declspec(dllexport) int _stdcall testAP(char* a)

こうしてください。

この回答への補足

度々すみません。
__declspec(dllexport) int _stdcall testAP(char* a)に変更したのですが、エントリtestAPがDLLファイル内に見つかりませんと言うメッセージが出力されます。

ご指摘がありましたらお願い致します。

補足日時:2003/11/21 14:29
    • good
    • 0

よくよく見ると



>int testAP( char* a)

呼び出し規約が無いですが平気ですか?。
VBから呼び出す場合は_stdcall規約です。

int _stdcall testAP( char* a)
とか
int WINAPI testAP( char* a)
になるはずです。

>Public Declare Function testAP Lib "test.dll" (ByVal keydata As String) As Integer

戻り値の型がIntegerになってます。
C側ではintなので、32bitですからLongにする必要があります。

で、あとは#4の方の指摘どおり、StrPtrが不要です。

#WindowsAPIの呼び出しってしたこと無いですか?

この回答への補足

すみません、C側は以下の記述を行ってDLLを作成してます。

__declspec(dllexport) int FAR testAP(char* a)

呼び出しは出来るのですが、aのアドレスがNULLです。


→ int _stdcall testAP(char* a)に修正した方が
いいのでしょうか?

ご指摘がありましたら、お願い致します。

補足日時:2003/11/21 12:48
    • good
    • 0

StringはByValで渡してください。


またStrPtrが不要です。
lngRc = testAP(keydata)

VB6では内部文字コードはUNICODEで保持しています。
一方CはSJISです。
StringをByValで渡すのは特別な意味があります。
暗黙的に一度SJISに変換してDLLに渡しています。

ByValといっても実際は参照渡しのようなもので
dll側で書き換えた文字列は
keydataに反映されます。

この回答への補足

ありがとうございます。

StrPtrを省略してデバックで検証したのですが、
DLL関数の受け側のポインタがNULLで設定されるため、
渡すことができません。。。

ご指摘通りにStringはByValにして、StrPtrを省略したのですが。。。まだ漏れている点がございましたらご指摘ください。

補足日時:2003/11/21 12:27
    • good
    • 0

>Public Declare Function testAP Lib "test.dll" (ByRef a As String) As Integer



正しくはByValです。
http://homepage2.nifty.com/newton/vbe/not_teach/ …


>/**** Cプログラム *****/
>int testAP( char* a)
>aのポインタにアドレスを返します。

ちなみにこれではポインタは返せませんよ。
ポインタの指す領域に文字列は返せますが。

本当にアドレスの値を返したいのであれば、
Win32であればポインタは32ビットなのでLongを使うことになります。

この回答への補足

ありがとうございます。
ご指摘通りポインタを指す領域に文字列も返します。

#1,2,3の方がのご指摘通りに、修正して行ったのですが、
今度は実行時エラー49 DLLが呼び出せませんと出力されすます。

このメッセージはVBからDLL関数を呼んで、関数を抜けて
VBに戻るときに出力されます。

VBの修正は以下の通りなのですが、誤りとあったらご指導お願い致します。

Public Declare Function testAP Lib "test.dll" (ByVal keydata As String) As Integer


Dim keydata As String * 128
lngRc = testAP(StrPtr(keydata))

補足日時:2003/11/21 11:28
    • good
    • 1

#1の方と同じですが、


VB6ならstrPtrが使えますが、.Netでは確認していません。

ret = testAP(strPtr(keydata))
で keydata をみてみてください。
    • good
    • 0

まったく自信ありません。

(^ ^;

1)strPtrを使用する(文字列のポインタを返します)

lngRc = testAP(strPtr(keydata))
ただし、strPtrは非公式関数みたいです。
.Netではなくなった?

2)Cのdefファイルの設定ミス
インタープリンター場で動かすと、アプリケーション
エラーで落ちますが、VBをexeにしたら落ちなかった
ことがあります。
何をどうすればと、きかれてもわかりません。
Cはよくわからないもので・・

参考になれば幸いです
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています