Link to home
Start Free TrialLog in
Avatar of petekipe
petekipeFlag for United States of America

asked on

What are the VB.NET data type equivalents for a Delphi function?

I need to use a dll developed in Delphi in my VB.NET application.  The Delphi developer has given me the function definition in Delphi:
function GenRegCode(
	RegStr : Widestring; 
	RegOptions, 
	SerialExpireDays,
        RegExpire, 
	RegExpireDays, 
	RegExpireMonths, 
	RegExpireYears : Integer;
        var Serial : Widestring) : LongBool; stdcall;

Open in new window

I'm attempting to call the entry point using the following VB definition:
    <DllImport("C:\Windows\SysWOW64\xxx.dll", EntryPoint:="GenRegCode", SetLastError:=True, _
        CharSet:=CharSet.Auto, ExactSpelling:=True, _
        CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function fGenRegCodeVB( _
        ByVal RegPassword As String, _
        ByVal RegOptions As Long, _
        ByVal SerialExpireDays As Long, _
        ByVal RegExpire As Long, _
        ByVal RegExpireDay As Long, _
        ByVal RegExpireMonth As Long, _
        ByVal RegExpireYear As Long, _
        ByRef Serial As String) As Boolean
    End Function

Open in new window

I'm getting an AccessViolationException error.  The string Serial is set to 1024 spaces -- much longer than the maximum string length that will be returned, which is 24.  Do I have the VB data types defined correctly?  Could this have something to do with a pointer to a string, versus the string itself?
Avatar of Ess Kay
Ess Kay
Flag of United States of America image

delphi data types can be found here
http://www.delphibasics.co.uk/Article.asp?Name=DataTypes
why don't you treat them all as string and convert them to what you need
Avatar of petekipe

ASKER

I'm not sure how I would treat all parameters as string in VB.NET and have the dll recognize them correctly...but following your link to Delphi data types, I've made changes to my function definition as follows:
    <DllImport("C:\Windows\SysWOW64\xxx.dll", EntryPoint:="GenRegCodeVB", SetLastError:=True, _
        CharSet:=CharSet.Auto, ExactSpelling:=True, _
        CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function GenRegCodeVB( _
        ByVal RegPassword As String, _
        ByVal RegOptions As Integer, _
        ByVal SerialExpireDays As Integer, _
        ByVal RegExpire As Integer, _
        ByVal RegExpireDay As Integer, _
        ByVal RegExpireMonth As Integer, _
        ByVal RegExpireYear As Integer, _
        ByRef Serial As String) As Boolean
    End Function

Open in new window

Here's the code that calls the function:
    Public Function bGenRegCode() As Boolean
        Dim liDay As Integer
        Dim liMonth As Integer
        Dim liYear As Integer

        Try
            If mbClassInitialized _
            And mbRegisteredNameSet _
            And mbStationNumberSet _
            And mbExpirationDateSet _
            And mbNumberOfMechanicsSet _
            And mbOptionsSet Then

                ' extract day month and year to integers
                liDay = CInt(mdExpirationDate.Day)
                liMonth = CInt(Month(mdExpirationDate))
                liYear = CInt(Year(mdExpirationDate))

                ' build the options integer (7 options in left nibble, # mechanics in right)
                If pfEncodeRegOptions() Then

                    ' make the receiving field big enough for serial number plus null
                    msSerialNumber = Space(32)

                    ' generate the serial number
                    If GenRegCodeVB(msRegisteredName & msStationNumber, _
                                     mshRegOptions, _
                                     0, _
                                     1, _
                                     liDay, _
                                     liMonth, _
                                     liYear, _
                                     msSerialNumber) Then

                        ' successful, clean up serial number and set good return
                        msSerialNumber = Left(msSerialNumber, 24)
                        mbSerialNumberSet = True
                        Return True

                    Else ' negative return from GenRegCode
                        msErrorMessage = msSerialNumber
                        Return False
                    End If

                Else ' negative return from pfEncodeRegOptions
                    Return False
                End If

            Else
                msErrorMessage = "Class not initialized, or required property not set"
                Return False
            End If

        Catch ex As Exception
            With System.Reflection.MethodBase.GetCurrentMethod()
                WriteErrorToLog(ex.ToString, .ReflectedType.Name & "." & .Name)
            End With
            Return False

        End Try
    End Function

Open in new window

I have a break point set on the call (line 26 above). When I step through the call, the program just ends, and I'm not getting any message relative to what went wrong.
Please provide more details:
- Q1: Is your Delphi dll compiled as Win32 dll?
- Q2: Which Delphi compiler version? Does it support Unicode?
- Q3: Is your .NET project build as "Any CPU" or x86?
- Q4: What sort of .NET project you have? Win Form/Asp.net/console, etc.?

An educated guess could be that there is a mismatch between .NET and Delphi especially if your >NET project is running in a 64 bit machine and is built as  "Any CPU" or x64. You can easily test it by changing the build to x86 and try again.
Q1:  (from the Delphi developer) Yes - the original dll is very old
Q2:  (from the Delphi developer) Delphi 7 using Widestrings - compatible with standard .NET strings. (COM compatible BSTR)
Q3:  x86
Q4:  Win Form

The latest appearance of the problem is that the call works without error, however the result I'm getting (in the last parameter, passed ByRef) looks like Chinese:  "ㅃ㔸䌭㕃ⵆ䙃㘶㠭䌹ⴸ䑂〹".  So the two string parameters probably aren't being specified correctly, but I don't know what to do to resolve the problem.

Any ideas would be greatly appreciated!
Oh and one more thing:  The old VB6 project runs perfectly against the dll on the same machine.  It has the numeric parameters typed as Long.
I think I may have a solution for this:  I've gone back to VB6 and created an ActiveX dll that invokes the Delphi dll.  It seems to be working from VB.NET, although I occasionally get Chinese characters back instead of what I'm expecting...still working on it.
Try replacing in VB.NET method with: (I use the same argument names as Delphi version and MarshalAs attribute)
Public Shared Function GenRegCodeVB( _
        ByVal RegStr As String, _
        ByVal RegOptions As Integer, _
        ByVal SerialExpireDays As Integer, _
        ByVal RegExpire As Integer, _
        ByVal RegExpireDays As Integer, _
        ByVal RegExpireMonths As Integer, _
        ByVal RegExpireYears As Integer, _
        <MarshalAs(UnmanagedType.BStr)> ByRef Serial As String) As Boolean
End Function

Open in new window

Notice that <MarshalAs(UnmanagedType.BStr)>  will force .NET to recognize the string as BSTR string and handle memory allocation for you.

If still does not work, please change Serial parameter in  your Delphi code (var Serial : Widestring)  as:
out Serial : Widestring
Note: From your code you are not passing any value(data) back to Delphi, but you are getting the serial string regardless of Serial initial value.
ASKER CERTIFIED SOLUTION
Avatar of petekipe
petekipe
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
None of the answers provided solved the problem.