Hello,
I want to pass a structure between VB (screen (form)) and VC++ (DLL), but it doesn't work...
Can i ask for your help? I want to borrow your wisdom, so let me ask you a question.
Sorry for my poor English.
First of all, it was originally developed with Visual Studio 6.0, and it was decided to convert the screen and DLL that were working stably, and I used the upgrade wizard function of Visual Studio 2008.
We understand that maintenance is required after use.
All warnings and errors were resolved, and after the build was completed, we checked the operation and proceeded with the maintenance of the parts that differed from the original operation. Among them, when I tried to refer to the structure that should have been edited by VC++ (DLL) in some processes on the VB side, I noticed that there was no data.
Maybe because of my lack of experience, I can't solve, and I can't get out of the problem.
My combination may be wrong.
Detailed information is provided below.
**Environment**
<Development Environment>
VisualStudio2008(VB、VC++)
※Convert what was developed with Visual Studio 6.0 with the upgrade wizard function,
We are in the process of converting.
Windows7 32bit
<Execution Environment>
Windows7 32bit
**Application Specification**
I would like it to work in the order 1 ⇒ 4.
1. Pass search condition x 1, repeat count x 1, empty structure x 1 from VB (screen (form)) to VC++ (DLL).
2. VC++ (DLL) searches the DB using the search condition as a key, and sets the search result in the structure passed from VB.
※With fetch, loop processing is performed for the number of iterations, and multiple records of information are obtained and set in the structure.
3. Return the structure set in 2 and the processing result (return code) to VB.
4. From the processing result (return code) received in 3, determine whether the VC++ processing is normal or abnormal,
If it is normal, the data of the structure is displayed on the screen.
**Problem Details**
Based on the above "Application Specifications", we will explain the specific operations.
In Stage 1, processing continues normally. (It is not possible to confirm whether it is the passed structure itself ...)
As in stage 2, processing continues normally. I was able to edit the structure defined by VC++ (DLL).
At stage 3, the process appears to have continued normally. At least the processing result returned normally.
Stage 4 discovers that the structure is empty, even though the processing results are correct.
Sadly, the result is "nothing on the screen".
In the preceding process (SELECT COUNT(*)) that is executed without any problems, there is no problem with the DB connection and SQL, and the value that is the processing result can be passed between VB and VC++.
Considering the difference from the preceding processing, I think there is a problem with the structure reference, but I don't have a solution...
**Program Source**
I will post the source of some applications as much as possible.
Comments are in Japanese. (Only important parts are translated into English.)
**<VB (screen (form))>**
**①API_Refer.vb**
Public Declare Function Esql_SelNonPosDetail Lib "Esql_Dll.dll" (ByVal SrvNum As String, ByRef RecordCnt As Long, ByRef dtpPS_Det() As tpPS_Det2) As Integer
**②mdlPKSrv.vb**
Public dtpPS_NonDet() As tpPS_Det2
Public Structure tpPS_GotData
Dim dtpPS_Hed As tpPS_Hed
Dim dtpPS_KaiDet() As tpPS_Det2
Dim dtpPS_NonDet() As tpPS_Det2
Dim dtpPS_Gaisho As tpPS_Gaisho
End Structure
Public Structure tpPS_Det2
Dim sShoriFlg As String
Dim sSrvNo As String
Dim sPosNo As String
Dim sTuuban As String
Dim sToriDate As String
Dim sToriTime As String
Dim sKingaku As String
Dim sRiyuCd As String
Dim sSrvRank As String
Dim sAddSrvRank As String
Dim sSrvTime As String
Dim sChgTime As String
Dim sHanbaiinCd As String
Dim sCustKbn As String
Dim sKozaNo As String
Dim sKozaSbh As String
End Structure
**③frmWork1.vb**
Private NPosRecCnt As Integer
~
Ret = Esql_NonPosCount(strPrkSrvNum, NPosRecCnt) ←"Number of repetitions"(NPosRecCnt)(No Problem)
If Ret <> 0 Then
Exit Function
Else
If NPosRecCnt > 0 Then
ReDim dtpPS_GotData(0).dtpPS_NonDet(NPosRecCnt - 1)
Ret = Esql_SelNonPosDetail(strPrkSrvNum, NPosRecCnt, dtpPS_GotData(0).dtpPS_NonDet) ←Problem spot! !
If Ret <> 0 Then
Exit Function
Else
**<VC++(DLL)>**
**④esql_com.h**
typedef struct {
BSTR szSyoriFlg; BSTR szServiceNo; BSTR szPosNo; BSTR szSeqNo; BSTR szCreateDate; BSTR szCreateTime; BSTR szSalMoney; BSTR szRiyuCode; BSTR szServiceRank; BSTR szAddSrvRank; BSTR szServiceTime; BSTR szChangeTime; BSTR szTantoCode; BSTR szCustKubn; BSTR szKozaNo; BSTR szKozaType; } NPOS_DET2;
**⑤Esql_com.sc**
__declspec(dllexport) int __stdcall Esql_SelNonPosDetail(char *lpszSrvNumber, long *nIndexNum, LPSAFEARRAY *pNpos_Det)
{
long lRet, lCount;
int ii;
int nSqlstate; char *work; NPOS_DET2 npos; LPSAFEARRAY psa = *pNpos_Det; int idx[1], lb, ub; static char bufa[1024]; static wchar_t bufw[1024]; size_t buft;
EXEC SQL SET TRANSACTION READ ONLY,
ISOLATION LEVEL READ UNCOMMITTED;
strrtrim(lpszSrvNumber);
strcpy_s(SQL_VARNUMBER.sqlvar,32, lpszSrvNumber);
SQL_VARNUMBER.sqllen = strlen(SQL_VARNUMBER.sqlvar);
strcpy_s(SQL_NUMBER,32, lpszSrvNumber);
if ( ( lRet = Esql_NonPosCount( SQL_NUMBER, &lCount ) ) != 0 ) {
return ( lRet );
}
if ( *nIndexNum < lCount ) {
return ( -1 );
}
setlocale(LC_ALL,"");
SafeArrayLock(psa);
SafeArrayGetLBound(psa, 1, &lb);
SafeArrayGetUBound(psa, 1, &ub);
idx[0] = lb;
EXEC SQL WHENEVER SQLERROR GOTO :SQL_ERROR;
EXEC SQL DECLARE NONPOS_CUR1 CURSOR FOR
SELECT SHORIFLG, SRVNO, POSNO, TUUBAN,
TORIDATE, TORITIME, KINGAKU, RIYUCD,
SRVRANK, SRVTIME, CHGTIME, HANBAIINCD,
CUSTOMKBN, KOZANO, KOZASBH
FROM PSSCH.NONPOSDET
WHERE SRVNO = :SQL_VARNUMBER;
EXEC SQL OPEN NONPOS_CUR1;
EXEC SQL WHENEVER NOT FOUND GOTO :SQL_NOT;
for ( ii = 0; ii < lCount; ii++ ) {
EXEC SQL FETCH FROM NONPOS_CUR1
INTO :SQL_SYORIFLG INDICATOR :SQL_HY01,
:SQL_KANRINO INDICATOR :SQL_HY02,
:SQL_POSNO INDICATOR :SQL_HY03,
:SQL_SEQNO INDICATOR :SQL_HY04,
:SQL_DATE INDICATOR :SQL_HY05,
:SQL_TIME INDICATOR :SQL_HY06,
:SQL_LNGSALMO INDICATOR :SQL_HY07,
:SQL_RIYUCD INDICATOR :SQL_HY08,
:SQL_RANK INDICATOR :SQL_HY09,
:SQL_LNGSRVTIME INDICATOR :SQL_HY10,
:SQL_LNGCHGTIME INDICATOR :SQL_HY11,
:SQL_TANTOCD INDICATOR :SQL_HY12,
:SQL_CUSTKBN INDICATOR :SQL_HY13,
:SQL_KOZANO INDICATOR :SQL_HY14,
:SQL_KOZATYPE INDICATOR :SQL_HY15;
SafeArrayGetElement(psa, &idx[0], &npos);
if (SQL_HY01 != -1) strncpy_s(bufa,sizeof(bufa), SQL_SYORIFLG, 2);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szSyoriFlg);
npos.szSyoriFlg = SysAllocString(bufw);
strncpy_s(bufa, sizeof(bufa),SQL_KANRINO, 16);
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szServiceNo);
npos.szServiceNo = SysAllocString(bufw);
strncpy_s(bufa, sizeof(bufa),SQL_POSNO, 6);
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szPosNo);
npos.szPosNo = SysAllocString(bufw);
strncpy_s(bufa, 6,SQL_SEQNO, 6);
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szSeqNo);
npos.szSeqNo = SysAllocString(bufw);
strncpy_s(bufa, sizeof(bufa),SQL_DATE, 10);
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szCreateDate);
npos.szCreateDate = SysAllocString(bufw);
strncpy_s(bufa, sizeof(bufa),SQL_TIME, 6);
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szCreateTime);
npos.szCreateTime = SysAllocString(bufw);
if (SQL_HY07 != -1) wsprintf(bufa, "%d", SQL_LNGSALMO);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szSalMoney);
npos.szSalMoney = SysAllocString(bufw);
strncpy_s(bufa, sizeof(bufa),SQL_RIYUCD, 4);
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szRiyuCode);
npos.szRiyuCode = SysAllocString(bufw);
if (SQL_HY09 != -1) strncpy_s(bufa, sizeof(bufa),SQL_RANK, 4);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szServiceRank);
npos.szServiceRank = SysAllocString(bufw);
if (SQL_HY10 != -1) wsprintf(bufa, "%d", SQL_LNGSRVTIME);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szServiceTime);
npos.szServiceTime = SysAllocString(bufw);
if (SQL_HY11 != -1) wsprintf(bufa, "%d", SQL_LNGCHGTIME);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szChangeTime);
npos.szChangeTime = SysAllocString(bufw);
if (SQL_HY12 != -1) strncpy_s(bufa, sizeof(bufa),SQL_TANTOCD, 10);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szTantoCode);
npos.szTantoCode = SysAllocString(bufw);
if (SQL_HY13 != -1) strncpy_s(bufa, sizeof(bufa),SQL_CUSTKBN, 4);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szCustKubn);
npos.szCustKubn = SysAllocString(bufw);
if (SQL_HY14 != -1) strncpy_s(bufa, sizeof(bufa),SQL_KOZANO, 27);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szKozaNo);
npos.szKozaNo = SysAllocString(bufw);
if (SQL_HY15 != -1) strncpy_s(bufa, sizeof(bufa),SQL_KOZATYPE, 4);
else *bufa = 0x00;
mbstowcs_s(&buft, bufw, sizeof(bufw), bufa, 1024);
SysFreeString(npos.szKozaType);
npos.szKozaType = SysAllocString(bufw);
SafeArrayPutElement(psa, &idx[0], &npos); ←Editing to "npos" works fine. SAFEARRAY structure can not be used in .net?
idx[0]++; }
SQL_NOT:
EXEC SQL CLOSE NONPOS_CUR1;
EXEC SQL COMMIT WORK;
SafeArrayUnlock(psa);
return ( 0 );
SQL_ERROR:
EXEC SQL WHENEVER SQLERROR CONTINUE;
nSqlstate = strtol(SQLSTATE,&work,16);
EXEC SQL CLOSE NONPOS_CUR1;
EXEC SQL ROLLBACK WORK;
SafeArrayUnlock(psa);
return ( nSqlstate );
}
Sorry for the long message.
Thank you.
What I have tried:
I have confirmed that the processing on the VC++ (DLL) side is being executed.
I know I'll need marshalling on the VB side, but I don't know how to combine it...
●「ByRef dtpPS_Det() As tpPS_Det2」→ ???
Public Declare Function Esql_SelNonPosDetail Lib "Esql_Dll.dll" (ByVal SrvNum As String, ByRef RecordCnt As Long, ByRef dtpPS_Det() As tpPS_Det2) As Integer