Hi James,
I would like to try to use bc9Basic to develop DLL functions passing strings in/out to PowerBasic executables using PB Strings (BSTR)
Do you have any example I can use as a start in order to understand how to do it?
Thanks a lot.
Eros
Eros,
BSTR's can be a bit of a pia :)
What c/c++ compiler will you be using?
What calling convention for the dll functions?
James
Eros,
Here is an example.
Note it is compiled as a c++ ($CPPHDR) dll so you have access to all the wonders of c++ and the STL.
Plus it seems it needs to be for the undecorated names to be created??
The dll was created with visual studio 2015 community.
James
bc9Basic Dll
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Eros BSTR test
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPPHDR
$DLL STDCALL
$ONEXIT "VSCPP.BAT $FILE$ -m32 dll Release"
Function MyDllFunction(strIn As char Ptr ) As BOOL EXPORT
Print strIn
Print "Hello from MyDllFunction"
Function = TRUE
End Function
'==============================================================================
Function GetTheString() As BSTR EXPORT
Dim S$
S$ = "Hello From the Dll"
Function = SysAllocStringByteLen(S$,Len(S$))
End Function
'==============================================================================
PowerBasic PBCC Test code.
#COMPILE EXE
#DIM ALL
DECLARE FUNCTION MyDllFunction LIB "Test2.Dll" ALIAS "MyDllFunction"(BYVAL S1 AS STRING) AS LONG
DECLARE FUNCTION GetTheString LIB "Test2.Dll" ALIAS "GetTheString"() AS STRING
FUNCTION PBMAIN () AS LONG
DIM S1 AS STRING
DIM RetVal AS LONG
S1 = "James"
RetVal = MyDllFunction(S1)
PRINT "RetVal = ";RetVal
S1 = GetTheString()
PRINT S1
END FUNCTION
Hi James,
thanks a lot. I just needed something to start.
Yes, calling convention is standard, VS2015 community is perfect.
My idea is to use bc9Basic to develop thinBasic modules (special DLLs) using thinBasic SDK interface. thinBasic is developed using PowerBasic so I needed an example on how to manage PB Strings in bc9Basic.
I already have possibility to use FreeBasic and FreePascal to develop thinBasic modules, I just wanted to give my user base another option.
I will experiment in next days and see what I can do.
Thanks again.
Eros
Eros,
Note, you must use my VSCPP.BAT file to get undecorated dll functions.
James
Thanks James,
I was able to compiler my first DLL.
I need to know if it is possible to have Pointer to a Function.
The equivalent in PowerBasic is CODEPTR
Thanks a lot
Eros
OK, I should have found: & in front of the function name.
Something like: &MyFunctionName
Is it correct?
Eros,
A bit different because we are not EXPORTing the calllback so we need to specify STDCALL for the callback.
The $DLL STDCALL defaults to EXPORTed procedures only.
James
bc9Basic test3.dll
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Eros BSTR test
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPPHDR
$DLL STDCALL
$ONEXIT "VSCPP.BAT $FILE$ -m32 dll Release"
'==============================================================================
Sub CallbackSub() STDCALL
Print "Hello From CallbackSub"
End Sub
'==============================================================================
Function MyDllFunction(strIn As char Ptr ) As BOOL EXPORT
Print strIn
Print "Hello from MyDllFunction"
Function = TRUE
End Function
'==============================================================================
Function GetTheString() As BSTR EXPORT
Dim S$
S$ = "Hello From the Dll"
Function = SysAllocStringByteLen(S$,Len(S$))
End Function
'==============================================================================
Function GetTheCallback() As DWORD EXPORT
Function = (DWORD)&CallbackSub
End Function
'==============================================================================
PowerBASIC
#COMPILE EXE
#DIM ALL
DECLARE FUNCTION MyDllFunction LIB "Test3.Dll" ALIAS "MyDllFunction"(BYVAL S1 AS STRING) AS LONG
DECLARE FUNCTION GetTheString LIB "Test3.Dll" ALIAS "GetTheString"() AS STRING
DECLARE FUNCTION GetTheCallback LIB "Test3.DLL" ALIAS "GetTheCallback"() AS DWORD
FUNCTION PBMAIN () AS LONG
DIM S1 AS STRING
DIM RetVal AS LONG
DIM dwCallBack As DWORD
S1 = "James"
RetVal = MyDllFunction(S1)
PRINT "RetVal = ";RetVal
S1 = GetTheString()
PRINT S1
dwCallBack = GetTheCallback
CALL DWORD dwCallBack
END FUNCTION
Eros,
You also can call pb subs/functions from the dll.
James
bc9Basic test4.dll
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'Eros BSTR test
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPPHDR
$DLL STDCALL
$ONEXIT "VSCPP.BAT $FILE$ -m32 dll Release"
'==============================================================================
'you need to define your pb sub/function like this
'this one is a Sub(void) with no paramaters
$TYPEDEF void (__stdcall *foo)()
' another example: we call a function that returns an int( pb long) passing a
' long(int) and a fixed length string
'$TYPEDEF int (__stdcall *foo1)(int,char*)
'==============================================================================
Sub CallbackSub() STDCALL
Print "Hello From CallbackSub"
End Sub
'==============================================================================
Function MyDllFunction(strIn As char Ptr ) As BOOL EXPORT
Print strIn
Print "Hello from MyDllFunction"
Function = TRUE
End Function
'==============================================================================
Function GetTheString() As BSTR EXPORT
Dim S$
S$ = "Hello From the Dll"
Function = SysAllocStringByteLen(S$,Len(S$))
End Function
'==============================================================================
Function GetTheCallback() As DWORD EXPORT
Function = (DWORD)&CallbackSub
End Function
'==============================================================================
Sub CallPbFunc(fooptr As foo) EXPORT
fooptr()
End Sub
'==============================================================================
PowerBASIC
#COMPILE EXE
#DIM ALL
DECLARE FUNCTION MyDllFunction LIB "Test4.Dll" ALIAS "MyDllFunction"(BYVAL S1 AS STRING) AS LONG
DECLARE FUNCTION GetTheString LIB "Test4.Dll" ALIAS "GetTheString"() AS STRING
DECLARE FUNCTION GetTheCallback LIB "Test4.DLL" ALIAS "GetTheCallback"() AS DWORD
DECLARE Sub CallPbFunc LIB "Test4.DLL" ALIAS "CallPbFunc"(BYVAL DWORD)
'==============================================================================
Sub PbCallBack()
Print "Here I am in the PbCallBack Sub"
End Sub
'==============================================================================
FUNCTION PBMAIN () AS LONG
DIM S1 AS STRING
DIM RetVal AS LONG
DIM dwCallBack As DWORD
S1 = "James"
RetVal = MyDllFunction(S1)
PRINT "RetVal = ";RetVal
S1 = GetTheString()
PRINT S1
dwCallBack = GetTheCallback
CALL DWORD dwCallBack
CallPbFunc(CODEPTR(PbCallBack))
END FUNCTION
Thanks a lot for those other explanations.
I've already done some tests on creating thinBasic modules with BC9 and it seems I'm able to do what I want.
During the weekend I will experiment more deeply but I'm quite happy about possibilities.
Thanks a lot
Eros