VC++呼び出し引数の順番による問題と解決方法

このQ&Aのポイント
  • 質問者はVB.Netで作成したアプリで、VC++で作成されたDLLを呼び出す際に、引数の順番による問題が発生している。
  • パターン1ではDLL側でchar変数に正しく値が設定されず、NULLになる現象が発生している。
  • VC++側がパターン1で作成されているため、VC++側の修正を行わずに問題を解決する方法はあるのか?
回答を見る
  • ベストアンサー

VB.netでのVC++呼び出し引数の順番

VC++で作成されたDLLをVB.NetにてそのDLLを呼び出すアプリを作成して います。以下のパターン2では問題なく動作しますが、パターン1では DLL側で見たときにchar変数に正しく値が入りません(NULL)になる。 パターン1とパターン2の違いは引数の順番です。 開発環境:VisualStudio2008 OS:WindowsXP SP2 パターン1(この場合はNG)  VC++側の宣言   extern "C" __declspec(dllexport) void func1(int i,char*s)  VB.Net側の宣言   <System.Runtime.InteropServices.DllImport("func.dll")> _   Public Sub func1(ByVal i As Long, ByVal s As String)   End Sub パターン2(この場合はOK)  VC++側の宣言   extern "C" __declspec(dllexport) void func1(char*s,int i)  VB.Net側の宣言   <System.Runtime.InteropServices.DllImport("func.dll")> _   Public Sub func1(ByVal s As String ,ByVal i As Long)   End Sub VC++側がパターン1で作成さているため、VC++側を修正をしないで 正常に動かすことは可能でしょうか? よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

> Public Sub func1(ByVal i As Long, ByVal s As String) Longではないのでは? intは32ビットの数値型ですので Integer か Int32 でどうでしょうか? パターン2の場合は引数が逆なのでたまたまうまくいくだけで、もしかしたら 別のところで弊害がでるかも。 (戻り値があったりするとうまくいかないかな)

maru_masa
質問者

お礼

bluecampus様 回答ありがとうございます。 Int32で問題なく動作いたしました。  VC++:int → VB.net:Int32 他の引数(longなど)も再度確認してみます。 お世話になりました。

関連するQ&A

  • C++製DLLにてVB.NET関数を引数付きでコールバックしたい。

    C++製DLLにてVB.NET関数を引数付きでコールバックしたい。 以下のようなソリューションがあります。 ソリューションには、VB.NETによるプロジェクトapp、C++によるプロジェクトdllがあり、 名前のとおり、appはWindowsフォームアプリケーション、dllはクラスライブラリです。 *** VisualStudio.NET 2003 ソリューション *** === VB.NETプロジェクト:app.exe === --- Module1.vb --- Module Module1 Delegate Function _t() As Int32 <System.Runtime.InteropServices.DllImport("dll.dll")> Public Function dllfunc(ByVal lpFunc As _t) As Int32 End Function End Module --- Form1.vb --- Public Class Form1 Inherits Form Private button1 As Button Public Sub New() button1 = New Button button1.Parent = Me : button1.Text = "button1" AddHandler button1.Click, AddressOf MyClass.GetEvent End Sub Private Sub GetEvent(ByVal sender As Object, ByVal e As EventArgs) dllfunc(AddressOf func1) End Sub Public Function func1() As Int32 MsgBox("func1@vb.net") Return 123 End Function End Class === C++ライブラリプロジェクト:dll.dll === --- dll.def --- LIBRARY dll EXPORTS dllfunc --- dll.h --- #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif DLL_API void dllfunc(int* vbfunc(void)); -- dll.cpp --- #include "stdafx.h" #include "dll.h" #include "stdio.h" #include "windows.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return true; } DLL_API void dllfunc(int* vbfunc(void)) { char str[16]; sprintf(str,"vbfunc() = %d",vbfunc()); MessageBoxA(NULL,str,"dll",MB_OK); } --- stdafx.cpp, stdafx.h --- (省略) *** ソリューション ここまで *** [ 動作 ] appを実行すると、Form1にbutton1が生成される。 button1をクリックするとGetEventが呼ばれ、func1のアドレスを引数としたdllfunc()を呼びます。 dll側のdllfunc()から、app側のfunc1()を呼び、戻り値の123を表示します。 [ 質問 ] dllfunc()から引数付きでfunc1()を呼びたいが、記述の方法が分かりません。 ご教示お願い致します。

  • 自作DLLの引数について、ポインタ渡しが??

    VS2005 VC++環境でMFCスマートデバイスDLLを作成しています(アプリ側もVS2005 VC++)。 テスト用のアプリからDLL内の文字列を引数とする関数を呼び出すと、 呼ばれた関数に正しく文字列が渡りません。 以下の場合、func1のw1はデバッガで正しく見れません。 でもw2にtcscpyは成功しw2には正しく値がセットされます。 このときにw1のアドレスがなぜか変更されます。 以下の例では引数が1つですが、2つ以上引数がある時には その他の引数のアドレスもとびます。 func2のl1は正常に見れます。 func3のl1は正常に見れません。 ポインタ渡しするときに異常になるのですが、 原因がさっぱりわかりません。 同じことをWindowsXP用のプロジェクトを作り、 XPで確認するとどれも正常に見れます。 どなたかアドバイスをお願いします。 ----------------------------------------DLL側---------------------------------------- extern "C" __declspec(dllexport) void func1(WCHAR * w1) { WCHAR w2[16] ; _tcscpy(w2,w1); return; } extern "C" __declspec(dllexport) void func2(long l1) { long l2 ; l2 = l1 ; return; } extern "C" __declspec(dllexport) void func3(long *l1) { long l2 ; l2 = *l1 ; return; } ----------------------------------------アプリ側---------------------------------------- extern "C" __declspec(dllimport) void func1(WCHAR *); extern "C" __declspec(dllimport) void func2(long ); extern "C" __declspec(dllimport) void func3(long *); ・・・・中略・・・・ WCHAR a[16] ; _tcscpy(a,_T("ABC")); func1(a); func2(123); long l3 = 123 ; func3(&l3);

  • VC2005のDLLを6.0で呼び出すには

    VC 2005 Pro Editionで作ったライブラリ(ヘッダ、lib、dll)を頂きました。    頂いたDLLの形式は定義ファイル.defを使わない形式、declspec(dllexport)を使う形式の方です。  呼び出し側はVC6.0EnterPrize(SDK)を使います。 (諸事情により6.0以上にUPすることは不可能)     まず、静的リンクをし、関数を呼び出してみました。  (設定のリンクよりlibをリンクさせ、ヘッダをインクルードして)  すると以下のメッセージが出てしまいます。 リンク中... Dialog1.obj : error LNK2001: 外部シンボル ""__declspec(dllimport) void __cdecl Init(unsigned char *,unsigned char *,unsigned char *,unsigned char *)" (__imp_?Init_Card@@YAXPAE000@Z)" は未解決です Debug/CardMake.exe : fatal error LNK1120: 外部参照 1 が未解決です 。 link.exe の実行エラー    色々やってみましたが、このエラーから回避できませんでした。  ヘッダ自体に #ifdef _USRDLL #define DLL_PORT __declspec(dllexport) #else #define DLL_PORT __declspec(dllimport) #endif    の宣言があるので、別に特別なことをしなくても、大丈夫そうなのですが、何故か出来ません。  次に動的リンクを行っていました。  するとLoadLibraryでエラーになり、GetLastErrrorで14001(エラーメッセージはつかめず)が返ってきました。 (色々調べたところ定義ファイルがないと動的リンクはできないようですね)    というわけでにっちもさっちも行かなくなった状況です。  そこでご質問です。 (1)定義ファイルを使わない形式のライブラリ(暗示的に定義されているもの)はどのように呼び出させばよいでしょうか? (2)2005のライブラリを6.0から呼び出すことは可能ですか?  また呼び出す方法は?  すいませんがご回答をお願いします。

  • VBからVCDLLへのtypedefパラメータの渡し方

    [VS2005 XP] お世話になります。 VCで作成したDLLをVBから呼び出したいのですが VC側 typedef unsigned int KTY[16];/*固定長配列*/ void AAA(const int Len, const unsigned char *str, KTY k){/*第三パラメータ k*/ ---- } VB側現在 <DllImport("***.dll")> _ Public Shared Sub AAA( _ ByVal Len As Integer, _ ByVal str As String, _ ByRef k() As UInt32) End Sub Dim kk() As UInt32 = Nothing Dim c As String = "1234567890" AAA(10, c, kk) ------- 第三パラメータをVC側で埋めて返してくれるはずなのですがNothingのままです。 typedefで固定長配列に宣言された値を取り出すにはどうしたらよいのでしょうか? VCは本日ソースを渡されただけで初めて触ります。 よろしくお願いいたします。

  • VC++6.0で作成したDLLのクラスをVB6.0でインポートするには?

    VC++6.0で作成したDLLのクラスをVB6.0でインポートするにはどうしたらいいのでしょうか? 通常の関数なら__declspec(dllexport) __stdcall を書き,defファイルにEXPORT指定することで解決できたのですが,クラスごとエクスポートする場合にはVC側,VB側の記述をどのようにすれば良いのでしょうか?

  • C#からVC++DLLの呼び出しに失敗する

    VS.NET2005のC#からVC++6.0で作成したDLLを呼び出しています。 VCのデバッガでデバッグしてみると呼び出した関数は正常に動作しているようなのですが、最後のreturnを実行しC#に戻るところでエラーが出てしまいます。 C#側では「'System.ExecutionEngineException' のハンドルされていない例外が ConsoleApplication1.exe で発生しました。」となります。 C#での宣言は、 [DllImport("test.dll")] public static extern uint TestFunc(ref byte[] moji, ref uint nagasa); です。 VC++の宣言は、 __declspec(dllexport) unsigned long __stdcall TestFunc(unsigned char* moji, unsigned long* nagasa) です。 C#へ値を返さない関数は問題ないのですが、値を返そうとすると起きるようです。不備などあればご指摘いただけないでしょうか。 ちなみにVB6からは問題なく動作できました。

  • Cで作成したDLL関数をVBから呼ぶ

    以前にあった「Cで作成したDLL関数をVBから呼び 引数渡し方法」を試したのですがVB側でデータが受け取れません。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=711327 C側での値設定がわるいのでしょうか? 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に値を設定する lpdata="ABCDEF"; }

  • VB.netの配列とVB6の配列の違い

    VB6で画面を作成し、演算処理を行うDLLをVC6で作成しています。 下記のコードでVB6でSingle型の2次元配列を宣言しま、VCのDLLでエクスポートしている関数に渡 します。 VC6DLL側のコード---------- EXPORT void __stdcall TESTFUNC (float *pfData,long nSize{ } VB側のコード---------- 宣言 Declare Function TESTFUNC Lib "TEST.dll" (ByRef pfData As Single, ByVal nSize As Long) As Long 配列宣言 Public sngDat(999,1) as single 呼び出し TESTFUNC sngDat(0,0),1000 このように呼び出した場合、VC6のTESTFUNC にブレークポイントを設定し、停止するとpfDataの ポインタをインクリメントした場合、sngDat(0,0),sngDat(1,0),sngDat(2,0)と、1次元目の添え字を インクリメントした状態になるように、メモリに格納されています。 この動作を前提として、VB.net側でも同じように呼び出してみました。 VB.net側のコード---------- 宣言 Declare Function TESTFUNC Lib "TEST.dll" (ByRef pfData As Single, ByVal nSize As Integer) As Integer 配列宣言 Public sngDat(999,1) as single 呼び出し TESTFUNC(sngDat(0,0),1000) VC側は全く同じコードを利用するとします。 同じように、VC6のTESTFUNC にブレークポイントを設定し、停止するとpfDataの ポインタをインクリメントした場合、sngDat(0,0),sngDat(0,1),sngDat(1,0)と,sngDat(1,1)、と1次元目の添え字を インクリメントせず、2次元目の添え字をインクリメントした状態になるように、メモリに格納されています。 VB6→VC6のDLLの場合の配列渡しと、VB.net→VC6のDLLの場合の配列渡しで違いがあるのは 何故でしょうか?また、VB.net側の配列渡しの仕様を、VB6側の仕様に合わせる方法は無いのでしょうか? よろしくお願いいたします。

  • VCでのDLLからVBへの文字列の引渡し

    ===VB(Ver.6.0 SP5)側=== Public Declare Function GetStrSample Lib "Test.dll" () As String ・・・・・ Label1.Caption = GetStrSample ===VC側(Ver6.0)=== const char *StrSample="ABCDE01234";   ・・・・ _declspec(dllexport) BSTR _stdcall GetStrSample() { CString strResult; strResult = StrSample; return strResult.AllocSysString(); } 上記のようなコードで、VC側をDLLとしてVBから呼び出すと、 Label1には "A" しか表示されず、ブレークを置いてGetStrSample の戻り値を調べてみると、0x41,0x00,0x42,0x00,のように、 0x00が挟まれてしまいました。 ( ?hex(asc(mid(GetStrSample,3,1))) のようにして調べました。)  何故なのでしょうか? 文字コードの違いでしょうか? 正常にABCDE01234が渡せるようにするにはどうすればいいでしょうか? VCは初心者で、本や他人の作ったコードやMSDNを見て作成してみました。 目的は、DLLのバージョン等の情報をVB側に渡したいのです。 よろしくお願いします。

  • Cで作成したDLL関数をVBから呼ぶ(.NET)

    以前の質問に「Cで作成したDLL関数をVBから呼ぶ」(QNo.1703839)がありますが、下記のコードを見るとVB6での内容だと思います。 Dim keydata As String * 128 keydata = String$(128, Chr(0) & Chr(0)) VB.NETでVC++のDLLで変更した文字列を受けたいのですが、 どのようにすればよいのでしょうか? VB.NET2003 <DllImport("DllTest.dll")> Private Shared Function _ Test(ByVal s1 As String) As String End Function Private Sub btnTest_Click(...) ... Dim s1 As String = "abc" Dim s2 As String Dim s3 As String s2 = Test(s1) MessageBox.Show(s2) ' "1"が表示される s3 = StrConv(s2, VbStrConv.None) MessageBox.Show(s3) ' 同じく"1"が表示 end sub VC++のDLL extern "C" __declspec (dllexport) BSTR __stdcall Test(char* s1) { AfxMessageBox(s1); // "abc"が表示される OK strcpy(s1, "123"); CString s2; s2 = "123"; return s2.AllocSysString(); } また、文字列に全角を含めても大丈夫でしょうか? Unicodeの変換処理を行う必要があるのでしょうか? よろしくお願いします。