こんにちは。
先日の質問では大変お世話になりました。
前回はVC++(DLL)がBSTR構造体で出力してVB(画面/フォーム)に渡す方法で行き詰まりましたが、今回はVB(画面/フォーム)からVC++(DLL)へ入力としてBSTR構造体を渡し参照する方法で行き詰まりました。
前回とは逆のことをやればよいと思ったのですが、思うようにいかず1週間以上苦戦しています…。
マネージド(VB.NET/Stringの構造体(n件))からアンマネージド(VC++/Bstrの構造体)へ直接構造体を受け渡す方法を教えていただけないでしょうか。
何卒よろしくお願いいたします。
<やりたいこと>
VBでマーシャリングした構造体をBSTR構造体としてVC++に渡す方法を知りたいです。
VB(screen/FORM):Structure(MarshalAs(UnmanagedType.Bstr))
↓
VC++(DLL):typedef(BSTR)
<開発環境>
Windows7(32bit)
VisualStudio2008(VB/VC++)
<実行環境>
Windows7(32bit)
試したこと:
以前の解決策を参考に以下のソースコードを試してみましたが、VC++側で構造体を参照するとエラーが発生しました。
「保護されたメモリに対して読み取りまたは書き込み操作を試みました。メモリが破損している可能性があります。」というエラーであるため、構造体自体をVBからうまく渡せていないか受け取れていないのではないかと未熟者ながら推察しております。
構造体を参照してからひとつひとつ別の構造体へ値を移していくやり方(wcsncpy_s,strncpy_s)も、MicrosoftやCODE PROJECTも使って調べながら組み込みましたが、果たして合っているか自信がありません。
構文が正しいのかという点でもアドバイスいただけましたら心から助かります。
VB側は「tpNonPosDet2」構造体を引数としてDLLの関数を呼び出し、VC++側は「NPOS_DETAIL_UPD2」構造体としてデータを受け取った後、SQL(DB更新)用の構造体「wk_Detail」に値を移し替えたいのです。
esql_com.h(C++)
1typedef struct { 2 char szFunctionFlag[2]; 3 char szServiceNo[16]; 4 char szPosNo[6]; 5 char szSeqNo[6]; 6 char szCreateDate[10]; 7 char szCreateTime[6]; 8 char szSalMoney[13]; 9 char szRiyuCode[4]; 10 char szServiceRank[4]; 11 char szServiceRankAdd[4]; 12 char szServiceTime[6]; 13 char szChangeTime[6]; 14 char szTantoCode[10]; 15 char szCustKubn[4]; 16 char szKozaNo[27]; 17 char szKozaType[4]; 18} NPOS_DETAIL_UPD; 19 20typedef struct { 21 BSTR szFunctionFlag; 22 BSTR szServiceNo; 23 BSTR szPosNo; 24 BSTR szSeqNo; 25 BSTR szCreateDate; 26 BSTR szCreateTime; 27 BSTR szSalMoney; 28 BSTR szRiyuCode; 29 BSTR szServiceRank; 30 BSTR szServiceRankAdd; 31 BSTR szServiceTime; 32 BSTR szChangeTime; 33 BSTR szTantoCode; 34 BSTR szCustKubn; 35 BSTR szKozaNo; 36 BSTR szKozaType; 37} NPOS_DETAIL_UPD2; 38 39 40 41 42__declspec(dllexport) int __stdcall Esql_UpNonPos(PS_HEADER_UPD *lpHeader, long *nIndexNum, NPOS_DETAIL_UPD2 *lpDetail);
esql_com.sc(C++)
1__declspec(dllexport) int __stdcall Esql_UpNonPos 2 (PS_HEADER_UPD *lpHeader, long *nIndexNum, NPOS_DETAIL_UPD2 *lpDetail) 3{ 4 long lCount=0; 5 int ii; 6 int nSqlstate; // SQL Return Code 7 char *work; // WorkArea 8 PS_HEADER_UPD wk_Header; // Header Information 9 NPOS_DETAIL_UPD wk_Detail; // Detail Information 10 long iRet; // Return Code 11 NPOS_DETAIL_UPD2 npos; // For structure reference 12// LPSAFEARRAY psa = *lpDetail; // For structure reference 13 int idx[1], lb, ub; // For structure reference 14 static char bufa[1024]; // For structure reference 15 static wchar_t bufw[1024]; // For structure reference 16 static size_t st; // Work Area 17 static char mbs[256]; // Test Area For MessageBox 18 19 20//***************************************************************************** 21// Processing start setting 22//***************************************************************************** 23 24 EXEC SQL WHENEVER SQLERROR GOTO :SQL_ERROR; 25 26 EXEC SQL SET TRANSACTION READ WRITE; 27 28//***************************************************************************** 29// SQL 30//***************************************************************************** 31 MessageBox( NULL, TEXT("Esql_UpNonPos"), TEXT("Esql_com.sc"), MB_OK); 32 MessageBox( NULL, TEXT(lpHeader->szServiceNo), TEXT("Esql_com.sc"), MB_OK); 33 34 35 36// Setting for structure reference 37//================================ 38 setlocale(LC_ALL,"Japanese"); 39// SafeArrayLock(psa); 40// SafeArrayGetLBound(psa, 1, &lb); 41// SafeArrayGetUBound(psa, 1, &ub); 42// idx[0] = lb; 43 idx[0] = 0; 44 45 46 47// Setting for detail information 48//================================ 49 EXEC SQL WHENEVER NOT FOUND CONTINUE; 50 for(ii=0; ii<*nIndexNum; ii++) { 51 // I used SAFEARRAY in VC++6.0, but I can't find a method that works well in VC++9.0, so I used another method. 52// SafeArrayGetElement(psa, &idx[0], &npos); 53 npos = lpDetail[idx[0]]; //←I get an error here. 54 55 // Reference of processing flag [add/delete etc] (obtained from argument structure) 56 MessageBox( NULL, TEXT(" 0.1 START"), TEXT("Esql_UpNonPos"), MB_OK); 57 *bufa = 0x00; 58 wcsncpy_s(bufw, 1024, npos.szFunctionFlag, 2); 59 wcstombs_s(&st, NULL, 0, &bufw, 1024); 60 wcstombs_s(&st, &bufa[0], st, &bufw, 1024); 61 memset(wk_Detail.szFunctionFlag, '\0', sizeof(wk_Detail.szFunctionFlag)); 62 strncpy_s(wk_Detail.szFunctionFlag, sizeof(wk_Detail.szFunctionFlag), bufa, 2-1); 63 MessageBox( NULL, TEXT(" 0.1 END"), TEXT("Esql_UpNonPos"), MB_OK); 64 MessageBox( NULL, TEXT(wk_Detail.szFunctionFlag), TEXT("Esql_UpNonPos Structure 1"), MB_OK); 65・ 66・ 67・
API_Refer.vb(VB)
1<DllImport("Esql_DLL.dll", CharSet:=CharSet.Ansi)> _ 2Public Function Esql_UpNonPos(<[In]()> ByVal Up_dtpPSHead As tpPS_Hed2, ByRef RecordCnt As Long, <[In]()> ByVal Up_dtpNonPosDet() As tpNonPosDet2) As Integer 3End Function
mdlPkSrv.vb(VB)
1 <StructLayout(LayoutKind.Sequential)> _ 2 Structure tpNonPosDet2 3 <MarshalAs(UnmanagedType.BStr)> Dim strShoriFlg As String 4 <MarshalAs(UnmanagedType.BStr)> Dim strSrvNo As String 5 <MarshalAs(UnmanagedType.BStr)> Dim strPosNo As String 6 <MarshalAs(UnmanagedType.BStr)> Dim strTuuban As String 7 <MarshalAs(UnmanagedType.BStr)> Dim strToriDate As String 8 <MarshalAs(UnmanagedType.BStr)> Dim strToriTime As String 9 <MarshalAs(UnmanagedType.BStr)> Dim strKingaku As String 10 <MarshalAs(UnmanagedType.BStr)> Dim strRiyuCd As String 11 <MarshalAs(UnmanagedType.BStr)> Dim strSrvRank As String 12 <MarshalAs(UnmanagedType.BStr)> Dim strAddSrvRank As String 13 <MarshalAs(UnmanagedType.BStr)> Dim strSrvTime As String 14 <MarshalAs(UnmanagedType.BStr)> Dim strChgTime As String 15 <MarshalAs(UnmanagedType.BStr)> Dim strHanbaiinCd As String 16 <MarshalAs(UnmanagedType.BStr)> Dim strCostomKbn As String 17 <MarshalAs(UnmanagedType.BStr)> Dim strKozaNo As String 18 <MarshalAs(UnmanagedType.BStr)> Dim strKozaSbh As String 19End Structure
frmPktest.vb(VB)
1Ret = Esql_UpNonPos(dtp_GotHedData, RecordCnt, dtp_NonPosDet)
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/12/01 09:37 編集
2022/12/01 13:50
2022/12/13 08:28
2022/12/13 09:14
2022/12/13 09:28
2022/12/13 11:29