|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Use of delegatea pointer to a structure. I am totally lost. Passing the pointer to rlistsys_resp_func and RLISTSYS_DETAIL is where I am lost. Any hint would be highly appreciated. C Header: _declspec(dllexport) extern void rlistsys(RLISTSYS_PARMS *rlistsys_parms, RLISTSYS_RESP *rlistsys_resp, void (*rlistsys_resp_func)(RLISTSYS_DETAIL *)); VB.NET Dim RLISTSYS_DETAIL As New TRLISTSYS_DETAIL Dim objDelegate As RLISTSYS_FUNC objDelegate = AddressOf RLISTSYS_FUNC_RUN rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, objDelegate, RLISTSYS_DETAIL) Module1 Public Delegate Sub RLISTSYS_FUNC(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) Public Sub RLISTSYS_FUNC_RUN(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) frmMain.grd.Rows.Add(CleanInput(RLISTSYS_DETAIL.name), CleanInput (RLISTSYS_DETAIL.description)) End Sub Public Declare Function rlistsys Lib "remotapi.dll" (ByRef RLISTSYS_PARMS As TRLISTSYS_PARMS, ByRef RLISTSYS_RESP As TRLISTSYS_RESP, ByRef objDelegate As RLISTSYS_FUNC, ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) As Integer Error: System.ArgumentException was unhandled Message="Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout." Source="Chainlinkwork" StackTrace: at Chainlinkwork.Module1.rlistsys(TRLISTSYS_PARMS& RLISTSYS_PARMS, TRLISTSYS_RESP& RLISTSYS_RESP, RLISTSYS_FUNC& objDelegate, TRLISTSYS_DETAIL& RLISTSYS_DETAIL) I tried to rewrite that into vb.net and am having difficulty
So can you re-word the problem? does it have to be written as the C part there? Can you explain the goal? The tradeoff (apparently) with unmanaged code is flexibility, maybe it cant be done the same? Show quoteHide quote "Bob Simoneau" <bobsimoneau@newsgroups.nospam> wrote in message news:u0ZDwfuEGHA.524@TK2MSFTNGP09.phx.gbl... > I am having a hard time with delegates, but here I must pass a delegate and > a pointer to a structure. I am totally lost. Passing the pointer to > rlistsys_resp_func and RLISTSYS_DETAIL is where I am lost. Any hint would > be highly appreciated. > > C Header: > _declspec(dllexport) extern void rlistsys(RLISTSYS_PARMS *rlistsys_parms, > RLISTSYS_RESP *rlistsys_resp, void (*rlistsys_resp_func)(RLISTSYS_DETAIL > *)); > > VB.NET > Dim RLISTSYS_DETAIL As New TRLISTSYS_DETAIL > Dim objDelegate As RLISTSYS_FUNC > objDelegate = AddressOf RLISTSYS_FUNC_RUN > rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, objDelegate, RLISTSYS_DETAIL) > > Module1 > Public Delegate Sub RLISTSYS_FUNC(ByRef RLISTSYS_DETAIL As > TRLISTSYS_DETAIL) > Public Sub RLISTSYS_FUNC_RUN(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) > frmMain.grd.Rows.Add(CleanInput(RLISTSYS_DETAIL.name), CleanInput > (RLISTSYS_DETAIL.description)) > End Sub > > Public Declare Function rlistsys Lib "remotapi.dll" (ByRef RLISTSYS_PARMS > As TRLISTSYS_PARMS, ByRef RLISTSYS_RESP As TRLISTSYS_RESP, ByRef > objDelegate As RLISTSYS_FUNC, ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) As > Integer > > > Error: > > System.ArgumentException was unhandled > Message="Type could not be marshaled because the length of an embedded > array instance does not match the declared length in the layout." > Source="Chainlinkwork" > StackTrace: > at Chainlinkwork.Module1.rlistsys(TRLISTSYS_PARMS& RLISTSYS_PARMS, > TRLISTSYS_RESP& RLISTSYS_RESP, RLISTSYS_FUNC& objDelegate, TRLISTSYS_DETAIL& > RLISTSYS_DETAIL) > > I have a DLL that was written in C many,many years ago. I do not have the
source code. I do have the C header file which has the declaration below. _declspec(dllexport) extern void rlistsys(RLISTSYS_PARMS *rlistsys_parms, RLISTSYS_RESP *rlistsys_resp, void (*rlistsys_resp_func)(RLISTSYS_DETAIL *)); I rewote the header into Delphi several years ago. Its declaration is below: function rlistsys(var INRLISTSYS_PARMS: TRLISTSYS_PARMS; var INRLISTSYS_RESP: TRLISTSYS_RESP; INListSYSFunc: TRListSysFunc): integer; cdecl; Now my company is changing to VB.NET 2005 and I am having trouble converting the code I basically have to call the rlistsys function passing two structures and a pointer to a callback function which take a structure as a parameter. "Brad Rogers" <bradz1234.nspam@yahoo.com> wrote in message news:4Bzvf.36$ww5.13@trnddc01...Show quoteHide quote >I tried to rewrite that into vb.net and am having difficulty > > So can you re-word the problem? does it have to be written as the C part > there? Can you explain the goal? > > The tradeoff (apparently) with unmanaged code is flexibility, maybe it > cant > be done the same? > > I am really suffering with the use of delegates. The Listsys function is
getting to me now. The C header declaration looks like below. Any clue on what a am doing wrong? _declspec(dllexport) extern void rlistsys(RLISTSYS_PARMS *rlistsys_parms, RLISTSYS_RESP *rlistsys_resp, void (*rlistsys_resp_func)(RLISTSYS_DETAIL *)); In the Module I declare the delegate Public Delegate Sub RLISTSYS_FUNC(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) In the main form I create the procedure Private Sub RLISTSYS_POPULATE(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) grd.Rows.Add(CleanInput(RLISTSYS_DETAIL.name), CleanInput(RLISTSYS_DETAIL.description)) End Sub On the button click I create a function variable, assign the address of the populate procedure, and then call the function Dim RLISTSYS_DETAIL As New TRLISTSYS_DETAIL Dim objDelegate As RLISTSYS_FUNC objDelegate = AddressOf RLISTSYS_POPULATE rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, objDelegate) The progran errors on the line above with "Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout" This one is tricky. Im not familiar enough with procedure on asking this in
the forum, but you could send me the code, nda, etc, I would have to see the error message generated on my machine and try some things The length gives errors ?? if you use ildasm does it give you any hints on length? because its involved with other code types, how do we know sizes? The delegate part seems to be okay, youre just calling it from addressof, but in vb.net its not just a pointer to function, but a type safe reference, from what I know they are not directly interchangeable. Show quoteHide quote "Bob Simoneau" <bobsimoneau@newsgroups.nospam> wrote in message news:%23sCZIbwEGHA.1676@TK2MSFTNGP09.phx.gbl... > I am really suffering with the use of delegates. The Listsys function is > getting to me now. The C header > declaration looks like below. Any clue on what a am doing wrong? > > _declspec(dllexport) extern void rlistsys(RLISTSYS_PARMS *rlistsys_parms, > RLISTSYS_RESP *rlistsys_resp, void (*rlistsys_resp_func)(RLISTSYS_DETAIL > *)); > > > In the Module I declare the delegate > Public Delegate Sub RLISTSYS_FUNC(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) > > In the main form I create the procedure > Private Sub RLISTSYS_POPULATE(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) > grd.Rows.Add(CleanInput(RLISTSYS_DETAIL.name), > CleanInput(RLISTSYS_DETAIL.description)) > End Sub > > On the button click I create a function variable, assign the address of the > populate procedure, and then call the function > > Dim RLISTSYS_DETAIL As New TRLISTSYS_DETAIL > Dim objDelegate As RLISTSYS_FUNC > objDelegate = AddressOf RLISTSYS_POPULATE > rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, objDelegate) > > The progran errors on the line above with > > "Type could not be marshaled because the length of an embedded array > instance does not match the declared length in the layout" > > > Hi Bob,
Thanks for your email. We did not have the declaration of the unmanaged dll and we did not have the source code, we did not provide support for a third party dll without source code to P/Invoke. In my test code, I try to pass the callback function point without another structure as the parameter. But the principle should be same. NOTE: a.return_text = New String("A", 200) a.size = Marshal.SizeOf(a) I create a string with 200 as we declare in the vb.net, if the value is less than 200, we will get the error. [.NET code] Imports System.Runtime.InteropServices Public Class Form1 Public Structure TRVERSION_PARMS Dim size As Integer ' REQUIRED Size of structure End Structure Public Structure TRVERSION_RESP Dim size As Integer ' REQUIRED Size of structure Dim return_code As Integer ' 0 if ( no error, != 0 if ( error <MarshalAs(UnmanagedType.ByValArray, SizeConst:=200)> _ Dim return_text() As Char ' Contains error text if return code != 0 <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Dim version() As Char ' DLL version End Structure Public RVERSION_PARMS As TRVERSION_PARMS Public RVERSION_RESP As TRVERSION_RESP Public Delegate Function MyDelegate(ByRef RVERSION_RESP As TRVERSION_RESP) As Integer Public Declare Function fnTestDLL Lib "TestDLL.dll" (ByRef RVERSION_PARMS As TRVERSION_PARMS, ByRef RVERSION_RESP As TRVERSION_RESP, ByVal md As MyDelegate) As Integer Public Declare Function fnTest1 Lib "TestDLL.dll" (ByRef RVERSION_RESP As TRVERSION_RESP) As Integer Public Function CallBackTest(ByRef RVERSION_RESP As TRVERSION_RESP) As Integer MsgBox(RVERSION_RESP.return_text) End Function Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click RVERSION_PARMS.size = Marshal.SizeOf(RVERSION_PARMS) RVERSION_RESP.size = Marshal.SizeOf(RVERSION_RESP) MsgBox(fnTestDLL(RVERSION_PARMS, RVERSION_RESP, AddressOf CallBackTest).ToString()) If (RVERSION_RESP.return_code <> 0) Then TextBox1.Text = "RVERSION ERROR: " & RVERSION_RESP.return_text Else TextBox1.Text = "RVERSION: " & RVERSION_RESP.version End If End Sub Dim a As TRVERSION_RESP Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click a.return_text = New String("A", 200) a.size = Marshal.SizeOf(a) fnTest1(a) End Sub End Class [C++ Test dll] #ifdef TESTDLL_EXPORTS #define TESTDLL_API __declspec(dllexport) #else #define TESTDLL_API __declspec(dllimport) #endif // This class is exported from the TestDLL.dll class TESTDLL_API CTestDLL { public: CTestDLL(void); // TODO: add your methods here. }; #define REQUEST_DECLINED -2 typedef struct rversion_parms_set_1 RVERSION_PARMS; typedef struct rversion_resp_set_1 RVERSION_RESP; #pragma pack(1) struct rversion_parms_set_1 { int size; /* REQUIRED Size of structure */ }; struct rversion_resp_set_1 { int size; /* REQUIRED Size of structure */ int return_code; /* = 0 if no error, != 0 if error */ char return_text[200]; /* Contains error text if return code != 0 */ char version[11]; /* DLL version */ }; #pragma pack() typedef int (__stdcall *pfnTest)(RVERSION_RESP* pt); extern TESTDLL_API int nTestDLL; extern "C" TESTDLL_API int fnTestDLL(RVERSION_PARMS *rversion_parms, RVERSION_RESP *rversion_resp,pfnTest pfn); extern "C" TESTDLL_API int fnTest1(RVERSION_RESP* pt); BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } #ifdef _MANAGED #pragma managed(pop) #endif // This is an example of an exported variable TESTDLL_API int nTestDLL=0; pfnTest p; // This is an example of an exported function. TESTDLL_API int fnTestDLL(RVERSION_PARMS *rversion_parms, RVERSION_RESP *rversion_resp,pfnTest pfn) { rversion_resp->return_code = 0; strcpy(rversion_resp->return_text,"Hello"); strcpy(rversion_resp->version,"World"); p= pfn; return 42; } TESTDLL_API int fnTest1(RVERSION_RESP* pt) { (*p)(pt); return 1; } // This is the constructor of a class that has been exported. // see TestDLL.h for the class definition CTestDLL::CTestDLL() { return; } Best regards, Peter Huang Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. Thank you so much for your previous help. I hope you don't mind me dipping
into the well of your knowledge again. I am really suffering with the use of delegates. I am using that same dll as you last helped me with. The Listsys function is getting to me now. The C header declaration looks like below. Any clue on what a am doing wrong? _declspec(dllexport) extern void rlistsys(RLISTSYS_PARMS *rlistsys_parms, RLISTSYS_RESP *rlistsys_resp, void (*rlistsys_resp_func)(RLISTSYS_DETAIL *)); In the Module I declare the delegate Public Delegate Sub MyDelegate(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) Public Declare Function rlistsys Lib "remotapi.dll" (ByRef RLISTSYS_PARMS As TRLISTSYS_PARMS, ByRef RLISTSYS_RESP As TRLISTSYS_RESP, ByVal myva As MyDelegate) As Integer In the main form I create the procedure Private Sub RLISTSYS_POPULATE(ByRef RLISTSYS_DETAIL As TRLISTSYS_DETAIL) Debug.write((RLISTSYS_DETAIL.name) End Sub On the button click I create a function variable, assign the address of the populate procedure, and then call the function Dim mydel As myDelegate mydel = AddressOf RLISTSYS_POPULATE rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, myDel) The progran errors on the line above with "Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout" Hi Bob,
Did you mean you test with the C++ as I post in my last post and you get the error? If so, can you send the C++ code to me? As I said before, without the C++ code it is hard to troubleshoot the problem and we did not support third party DLL without source code. Also as I said in my last post, we may need to fill the char array with the correct length, you may have a try. e.g. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdListSys.Click Dim RLISTSYS_PARMS As New TRLISTSYS_PARMS Dim RLISTSYS_RESP As New TRLISTSYS_RESP RLISTSYS_PARMS.size = Marshal.SizeOf(RLISTSYS_PARMS) RLISTSYS_RESP.size = Marshal.SizeOf(RLISTSYS_RESP) RLISTSYS_PARMS.hostname = edtHost.Text & New String(Chr(0), 101 - Len(edtHost.Text)) RLISTSYS_PARMS.system_user = "CHAINLNK" & New String(Chr(0), 101 - 8) RLISTSYS_PARMS.system_password = "CHAINLNK" & New String(Chr(0), 101 - 8) RLISTSYS_PARMS.system_select = edtSysSelect.Text & New String(Chr(0), 11 - Len(edtSysSelect.Text)) RLISTSYS_PARMS.system_name = "*" & New String(Chr(0), 11 - 1) Dim RLISTSYS_DETAIL As New TRLISTSYS_DETAIL Dim objDelegate As RLISTSYS_FUNC objDelegate = AddressOf RLISTSYS_POPULATE rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, objDelegate) If RLISTSYS_RESP.return_code <> 0 Then grd.AllowUserToAddRows = False grd.Columns.Clear() grd.Columns.Add("Response", "Response") grd.Rows.Add("RLISTSYS ERROR: " & CleanInput(RLISTSYS_RESP.return_text)) Else grd.AllowUserToAddRows = False grd.Columns.Clear() grd.Columns.Add("Name", "Name") grd.Columns.Add("Description", "Description") End If End Sub Best regards, Peter Huang Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. I included the remotapi.h in this projects zip, which I just e-mailed to
you. I only have the header source, I do not have the source for the DLL. The code you last put on this newsgroup helped. I get all the way to the function call now (I no longer get the error: Type could not be marshaled because the length of an embedded array instance does not match the declared length in the layout.) But the dll does not like the data passed. In delphi I have the data such as HUB01 padded on the right with #0 which is an ansi null. The vb code is padded with [Nothing] how do a pad the array with ansi nulls. host_name = 'HUB01" & new String(chr(0),11) does not seem to work with the DLL. Show quoteHide quote ""Peter Huang" [MSFT]" <v-phu***@online.microsoft.com> wrote in message news:5GiamxYFGHA.3764@TK2MSFTNGXA02.phx.gbl... > Hi Bob, > > Did you mean you test with the C++ as I post in my last post and you get > the error? > If so, can you send the C++ code to me? As I said before, without the C++ > code it is hard to troubleshoot the problem and we did not support third > party DLL without source code. > > Also as I said in my last post, we may need to fill the char array with > the > correct length, you may have a try. > e.g. > Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As > System.EventArgs) Handles cmdListSys.Click > Dim RLISTSYS_PARMS As New TRLISTSYS_PARMS > Dim RLISTSYS_RESP As New TRLISTSYS_RESP > RLISTSYS_PARMS.size = Marshal.SizeOf(RLISTSYS_PARMS) > RLISTSYS_RESP.size = Marshal.SizeOf(RLISTSYS_RESP) > RLISTSYS_PARMS.hostname = edtHost.Text & New String(Chr(0), 101 - > Len(edtHost.Text)) > RLISTSYS_PARMS.system_user = "CHAINLNK" & New String(Chr(0), 101 - > 8) > RLISTSYS_PARMS.system_password = "CHAINLNK" & New String(Chr(0), > 101 - 8) > RLISTSYS_PARMS.system_select = edtSysSelect.Text & New > String(Chr(0), 11 - Len(edtSysSelect.Text)) > RLISTSYS_PARMS.system_name = "*" & New String(Chr(0), 11 - 1) > Dim RLISTSYS_DETAIL As New TRLISTSYS_DETAIL > Dim objDelegate As RLISTSYS_FUNC > objDelegate = AddressOf RLISTSYS_POPULATE > rlistsys(RLISTSYS_PARMS, RLISTSYS_RESP, objDelegate) > If RLISTSYS_RESP.return_code <> 0 Then > grd.AllowUserToAddRows = False > grd.Columns.Clear() > grd.Columns.Add("Response", "Response") > grd.Rows.Add("RLISTSYS ERROR: " & > CleanInput(RLISTSYS_RESP.return_text)) > Else > grd.AllowUserToAddRows = False > grd.Columns.Clear() > grd.Columns.Add("Name", "Name") > grd.Columns.Add("Description", "Description") > End If > End Sub > > Best regards, > > Peter Huang > Microsoft Online Partner Support > > Get Secure! - www.microsoft.com/security > This posting is provided "AS IS" with no warranties, and confers no > rights. > Hi
Based on my test with my C++ dll in in the post before last. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click a.return_text = "Test" & New String(chr(0), 200 - 4) a.size = Marshal.SizeOf(a) fnTest1(a) End Sub If I pass a string as above code, in the C++ DLL side I set a debug point in the C++ side. And find that what I have passed into the C++ side as below. T e s t 0 0 0 0 ... 0 Which is just we are want to pass in the C++. That is why I said without the C++ source code we can not do further troubleshooting. Because we did not know what the C++ side want and know what we are passing into unmanaged code exactly. Best regards, Peter Huang Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. OK. Thanks for all your help. I understand that without the C++ source code,
it is hard to debug. I do know what the C++ side wants, as I have a working Delphi application which I wrote. I can clearing see that the array elements are passed padded with ansi nulls(#0). The managed code shows "h"c, "u"c, "b"c, "0"c, "1"c, nothing, nothing, nothing, nothing, nothing, nothing. The delphi code is passing 'h','u','b','0','1',#0, #0, #0, #0, #0, #0. I do appreciate all your time and effort, I can see from your code sample below, that they should be the same. I will re-group and re-examine my code. There has to be something changing, as it works with the Delphi code, but not the VB.NET The whole project of the Point of Sale conversion from Delphi to VB.NET relies on that Chainlink DLL, and is now on hold. Show quoteHide quote ""Peter Huang" [MSFT]" <v-phu***@online.microsoft.com> wrote in message news:<nrhjO7lFGHA.224@TK2MSFTNGXA02.phx.gbl>... > Hi > > Based on my test with my C++ dll in in the post before last. > Private Sub Button2_Click(ByVal sender As System.Object, ByVal e > As > System.EventArgs) Handles Button2.Click > a.return_text = "Test" & New String(chr(0), 200 - 4) > a.size = Marshal.SizeOf(a) > fnTest1(a) > End Sub > > If I pass a string as above code, in the C++ DLL side I set a debug > point in the C++ side. > And find that what I have passed into the C++ side as below. > T > e > s > t > 0 > 0 > 0 > 0 > .. > 0 > > Which is just we are want to pass in the C++. > > That is why I said without the C++ source code we can not do further > troubleshooting. Because we did not know what the C++ side want and > know what we are passing into unmanaged code exactly. > > Best regards, > > Peter Huang > Microsoft Online Partner Support > > Get Secure! - www.microsoft.com/security This posting is provided "AS > IS" with no warranties, and confers no rights. > ""Peter Huang" [MSFT]" <v-phu***@online.microsoft.com> wrote in message news:nrhjO7lFGHA.224@TK2MSFTNGXA02.phx.gbl... > Hi > > Based on my test with my C++ dll in in the post before last. > Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As > System.EventArgs) Handles Button2.Click > a.return_text = "Test" & New String(chr(0), 200 - 4) > a.size = Marshal.SizeOf(a) > fnTest1(a) > End Sub > > If I pass a string as above code, in the C++ DLL side I set a debug point > in the C++ side. > And find that what I have passed into the C++ side as below. > T > e > s > t > 0 > 0 > 0 > 0 > .. > 0 > > Which is just we are want to pass in the C++. > > That is why I said without the C++ source code we can not do further > troubleshooting. Because we did not know what the C++ side want and know > what we are passing into unmanaged code exactly. > > Best regards, > > Peter Huang > Microsoft Online Partner Support > > Get Secure! - www.microsoft.com/security > This posting is provided "AS IS" with no warranties, and confers no > rights. > Hi Bob,
Thanks for your update and feedback. Because I am not familar with the Delphi, I did not know what is the internal mechanism of the Delphi to call an C++ DLL. But I think you may try to write a C++ dll and use a Delphi to call the dll to see what will be passed into the dll. That way you will have a source code and you will compare the different between delphi and vb.net. Thanks for your understanding! Best regards, Peter Huang Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. Thanks once again for the help. I do not know c++ well enough to write a
DLL. The previous problem was because I had two parameters reversed. I now have the callback being preformed. The problem is that the callback only occurs once. What I mean is. If I run the Delphi program, the grid gets populated with four rows of data. If I run the VB code below, only one row gets populated, which is the first row shown in the delphi program. Any hints? Imports System.Runtime.InteropServices Imports System.Text Public Class frmMain Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load End Sub Private Sub RLIST_POPULATE(ByRef inRLIST_DETAIL As TRLIST_DETAIL) Try Dim source As String Dim RegNum As String Dim Target As String Dim ref_id_1 As String Dim ref_id_2 As String Dim lvDate As String Dim lvTime As String source = StripNull(inRLIST_DETAIL.source_name) RegNum = StripNull(inRLIST_DETAIL.request_nbr) Target = StripNull(inRLIST_DETAIL.target_name) ref_id_1 = StripNull(inRLIST_DETAIL.ref_id_1) ref_id_2 = StripNull(inRLIST_DETAIL.ref_id_2) & " " lvDate = StripNull(inRLIST_DETAIL.creation_date) lvTime = StripNull(inRLIST_DETAIL.creation_time) Dim row1 As String() = {source, RegNum, Target, ref_id_1, ref_id_2, lvDate, lvTime} grd.Rows.Add(row1) Catch MessageBox.Show("Error in Populate") End Try End Sub Private Sub cmdList_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdList.Click grd.AllowUserToAddRows = False grd.Columns.Clear() grd.Columns.Add("Source", "Source") grd.Columns.Add("RegNum", "RegNum") grd.Columns.Add("Target", "Target") grd.Columns.Add("Ref_id_1", "Ref_id_1") grd.Columns.Add("Ref_id_2", "Ref_id_2") grd.Columns.Add("Date", "Date") grd.Columns.Add("Time", "Time") RLIST_PARMS.size = Marshal.SizeOf(RLIST_PARMS) RLIST_RESP.size = Marshal.SizeOf(RLIST_RESP) RLIST_PARMS.ref_id_1 = edtRef1.Text & New String(Chr(0), 11 - Len(edtRef1.Text)) RLIST_PARMS.hostname = edtHost.Text & New String(Chr(0), 101 - Len(edtHost.Text)) RLIST_PARMS.system_user = "CHAINLNK" & New String(Chr(0), 101 - 8) RLIST_PARMS.system_password = "CHAINLNK" & New String(Chr(0), 101 - 8) RLIST_PARMS.system_select = edtStore.Text & New String(Chr(0), 11 - Len(edtStore.Text)) RLIST_PARMS.target_name = edtStore.Text & New String(Chr(0), 11 - Len(edtStore.Text)) RLIST_PARMS.proc_status_code = "REA" & New String(Chr(0), 4 - 3) RLIST_PARMS.source_name = edtSource.Text & New String(Chr(0), 11 - Len(edtSource.Text)) Dim cb As New ListDelegate(AddressOf RLIST_POPULATE) Try rlist(RLIST_PARMS, RLIST_RESP, cb) Catch End Try If RLIST_RESP.return_code <> 0 Then grd.AllowUserToAddRows = False grd.Columns.Clear() grd.Columns.Add("Response", "Response") grd.Rows.Add("RLIST ERROR: " & StripNull(RLIST_RESP.return_text)) End If End Sub End Class Imports System.Runtime.InteropServices Imports System.Text.RegularExpressions Module Module1 <StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)> _ Public Structure TRLIST_DETAIL <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ Public compress_code() As Char Public container_size As Integer <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ Public contents_code() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public creation_date() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=9)> _ Public creation_time() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public failure_reason() As Char Public image_size As Integer <MarshalAs(UnmanagedType.ByValArray, SizeConst:=51)> _ Public object_title() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=31)> _ Public original_file_name() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public original_file_date() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=9)> _ Public original_file_time() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ Public proc_status_code() As Char Public record_count As Integer Public record_len As Integer <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public ref_id_1() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=31)> _ Public ref_id_2() As Char Public request_nbr As Integer <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public source_name() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public target_name() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ Public xmit_status_code() As Char Public imm_xmit_tries As Byte Public reg_xmit_tries As Byte End Structure <StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)> _ Public Structure TRLIST_PARMS Public size As Integer <MarshalAs(UnmanagedType.ByValArray, SizeConst:=101)> _ Public hostname() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ Public proc_status_code() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public ref_id_1() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=31)> _ Public ref_id_2() As Char Public request_nbr As Integer <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public source_name() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public old_system_password() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public old_system_user() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public target_name() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=101)> _ Public system_password() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=101)> _ Public system_user() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=11)> _ Public system_select() As Char <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> _ Public xmit_status_code() As Char End Structure <StructLayout(LayoutKind.Sequential, Pack:=1, CharSet:=CharSet.Ansi)> _ Public Structure TRLIST_RESP Public size As Integer ' REQUIRED Size of structure Public return_code As Integer ' 0 if no error, != 0 if error <MarshalAs(UnmanagedType.ByValArray, SizeConst:=200)> _ Public return_text() As Char ' Contains error text if return code != 0 End Structure Public RLIST_PARMS As New TRLIST_PARMS Public RLIST_RESP As New TRLIST_RESP Public Delegate Sub ListDelegate(ByRef RLIST_DETAIL As TRLIST_DETAIL) Public Declare Sub rlist Lib "remotapi.dll" (ByRef RLIST_PARMS As TRLIST_PARMS, ByRef RLIST_RESP As TRLIST_RESP, ByVal myvli As ListDelegate) Public Function StripNull(ByVal InString As String) As String Dim iNull As Integer Dim wrkstr As String wrkstr = "" If Len(InString) > 0 Then iNull = InStr(InString, vbNullChar) Select Case iNull Case 0 wrkstr = InString Case 1 wrkstr = "" Case Else wrkstr = Left$(InString, iNull - 1) End Select End If Return wrkstr End Function End Module Hi Bob,
Since the callback is called by C++ code, if we did not dig into the C++ source code, we have no idea about what may be the error. I suggest you contact the C++ DLL development for the source code. Thanks for your understanding! Best regards, Peter Huang Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. The developers are long out of business. It must have something to do with
Marshaling, as a call from other languages perform properly. I suspect that after the delegate is used by the DLL, that the procedure pointed to in memory gets moved. Does that make sense? Show quoteHide quote ""Peter Huang" [MSFT]" <v-phu***@online.microsoft.com> wrote in message news:l5zqr5$FGHA.3944@TK2MSFTNGXA02.phx.gbl... > Hi Bob, > > Since the callback is called by C++ code, if we did not dig into the C++ > source code, we have no idea about what may be the error. > I suggest you contact the C++ DLL development for the source code. > > Thanks for your understanding! > > Best regards, > > Peter Huang > Microsoft Online Partner Support > > Get Secure! - www.microsoft.com/security > This posting is provided "AS IS" with no warranties, and confers no > rights. > The callback appears to work, but when it trys to update the
TLIST_RESP.return_text it errors with: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Bob Simoneau wrote: Show quoteHide quote > The developers are long out of business. It must have something to do with > Marshaling, as a call from other languages perform properly. I suspect that > after the delegate is used by the DLL, that the procedure pointed to in > memory gets moved. Does that make sense? > > ""Peter Huang" [MSFT]" <v-phu***@online.microsoft.com> wrote in message > news:l5zqr5$FGHA.3944@TK2MSFTNGXA02.phx.gbl... > > Hi Bob, > > > > Since the callback is called by C++ code, if we did not dig into the C++ > > source code, we have no idea about what may be the error. > > I suggest you contact the C++ DLL development for the source code. > > > > Thanks for your understanding! > > > > Best regards, > > > > Peter Huang > > Microsoft Online Partner Support > > > > Get Secure! - www.microsoft.com/security > > This posting is provided "AS IS" with no warranties, and confers no > > rights. > > Hi Bob,
Thanks for your feedback. It seems that you have opened a new thread for this problem. We will follow up in that thread. Thanks! Best regards, Peter Huang Microsoft Online Partner Support Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. I have a small project which shows the problem which I can send to anyone
who thinks they might be able to help. I did not want to burden the dial-up people, so I did not attach it. Thanks in advance.
SetWindowsHookEx and VB.NET 2005
A Framework for Datadriven Forms for VB Dot Net XML Comments File Generated Byte Array, Datagrid Simple Example of How to Implement SerialPort Class CreateObject( )... :( Problem with setting focus DataSet Problems I was looking for the "Immediate" window like in Classic VB but can't find it ISO Date Functions |
|||||||||||||||||||||||