petekipe
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;
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
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?
why don't you treat them all as string and convert them to what you need
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
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
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: 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.
ASKER
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!
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!
ASKER
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.
ASKER
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)
Str)> 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.
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
Notice that <MarshalAs(UnmanagedType.BIf 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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
None of the answers provided solved the problem.
http://www.delphibasics.co.uk/Article.asp?Name=DataTypes