scan DLL source files to make wrapper
Posted: Wed Jan 30, 2008 4:15 am
Here is a little code I used to scan Chipmunk DLL source.( .H .C files)
You need :
- DLL sources (coded in C )
- compiled DLL
You need :
- DLL sources (coded in C )
- compiled DLL
Code: Select all
Global SourceDir.s = GetPathPart(ProgramFilename())
Global DllFile.s="chipmunk-4.0.2.dll"
Debug "Search in directory = "+SourceDir
Debug "DLL = "+DllFile
; =======================
; get .H and .C source files
; =======================
Global NewList SourceFiles.s()
Procedure.s GetSourceTexts(file.s)
If ReadFile(0,file)
;read file to string
Protected lof = Lof(0)
Protected text.s=Space(lof+1)
ReadData(0,@text,lof)
CloseFile(0)
;remove 'C' comments
CreateRegularExpression(1, "[/]{2,}[^\r^\n]*")
If MatchRegularExpression(1,text)
text=ReplaceRegularExpression(1,text,"")
EndIf
ProcedureReturn text
EndIf
ProcedureReturn ""
EndProcedure
Procedure GetSourceFiles()
If ExamineDirectory(0,SourceDir,"*.h")
While NextDirectoryEntry(0)
If DirectoryEntryType(0) = #PB_DirectoryEntry_File
AddElement(SourceFiles())
SourceFiles()= DirectoryEntryName(0)
EndIf
Wend
FinishDirectory(0)
EndIf
If ExamineDirectory(0,SourceDir,"*.c")
While NextDirectoryEntry(0)
If DirectoryEntryType(0) = #PB_DirectoryEntry_File
AddElement(SourceFiles())
SourceFiles()= DirectoryEntryName(0)
EndIf
Wend
FinishDirectory(0)
EndIf
EndProcedure
GetSourceFiles()
; =======================
; get functions from text
; =======================
Global NewList DllFunc.s()
Global NewList DllFuncDECL.s()
Procedure GetDLLFunctions()
;{ REGEX HELP FILE
; CreateRegularExpression(#RegularExpression, Pattern$) - Create a new regular expression.
; ExtractRegularExpression(#RegularExpression, String$, Array$()) - Extract strings according To the regular expression into an array.
; IsRegularExpression(#RegularExpression) - Tests If the given '#RegularExpression' is an initialized regular expression object.
; MatchRegularExpression(#RegularExpression, String$) - Tests If a string match the regular expression.
; ReplaceRegularExpression(#RegularExpression, String$, ReplaceString$) - Replace some strings according To the regular expression.
; RegularExpressionError() - Return the last regular expression error.
;}
Debug "[ Dll Functions ]"
; =======================
; get DLL functions
; =======================
If OpenLibrary(0,DllFile)
If ExamineLibraryFunctions(0)
While NextLibraryFunction()
AddElement(DllFunc())
AddElement(DllFuncDECL())
DllFunc()= LibraryFunctionName()
Wend
EndIf
EndIf
; =======================
; scan each sourcefile
; =======================
Protected Dim Found.s(0)
ForEach SourceFiles()
Debug "-"+SourceFiles()
Protected text.s = GetSourceTexts(SourceFiles())
If text.s<>""
ResetList(DllFuncDECL())
ResetList(DllFunc())
While NextElement(DllFunc()) And NextElement(DllFuncDECL())
If DllFuncDECL()<>""
Continue
EndIf
; =======================
; parse text
; =======================
CreateRegularExpression(1, "[\w]{3,}[ \t*]+"+DllFunc()+"[ \t]*[(][^)]*[)]")
If Not MatchRegularExpression(1, text)
CreateRegularExpression(1, "[\w]*[ \t]*[\w]+[ \t]+"+DllFunc()+"[^;]*")
If Not MatchRegularExpression(1, text)
Continue
EndIf
EndIf
; =======================
; find function
; =======================
ReDim Found.s(0)
Protected count = ExtractRegularExpression(1, text, Found.s())
DllFuncDECL()=Found(0)
If count>1
For i=0 To count-1
Debug " >("+Str(i+1)+") "+Found(i)
Next
Debug ""
Else
Debug " >"+ DllFuncDECL()
EndIf
Wend
EndIf
Next
ResetList(DllFuncDECL())
ResetList(DllFunc())
While NextElement(DllFunc()) And NextElement(DllFuncDECL())
If DllFuncDECL()=""
MessageRequester("ERROR","missing functions :"+DllFunc())
End
EndIf
Wend
Debug ""
EndProcedure
GetDLLFunctions()
; =======================
; convert functions
; ( and register all needed types )
; =======================
Global NewList DllType.s()
Global NewList DllTypeDECL.s()
Procedure RegisterDllType(NewType.s)
NewType=Trim(RemoveString(NewType,#TAB$))
Select NewType
Case "f","l","c","void"
ProcedureReturn
EndSelect
ForEach DllType()
If DllType()=NewType
ProcedureReturn
EndIf
Next
AddElement(DllType())
AddElement(DllTypeDECL())
DllType()=NewType
Debug "---------------->"+ DllType();+" "+Str(Len(NewType))
EndProcedure
Procedure.s GetDllType(SourceCode.s,ReturnType.b=0)
;TEST : extern const usigned int **sfsdfs
SourceCode=ReplaceString(SourceCode,"*"," *")
CreateRegularExpression(1,"[*][ \t]+")
SourceCode=ReplaceRegularExpression(1,SourceCode,"*")
SourceCode=Trim(SourceCode)
CreateRegularExpression(1,"[ \t]+")
SourceCode=ReplaceRegularExpression(1,SourceCode," ")
;TEST : EXCUInt **sfsdfs
Protected ConvertedType.s=SourceCode
Protected varSuffix.s
If FindString(ConvertedType,"extern ",1)
ConvertedType=RemoveString(ConvertedType,"const ")
varSuffix+"EX"
EndIf
If FindString(ConvertedType,"const ",1)
ConvertedType=RemoveString(ConvertedType,"const ")
varSuffix+"CS"
EndIf
If FindString(ConvertedType,"unsigned ",1)
ConvertedType=RemoveString(ConvertedType,"unsigned ")
varSuffix+"U"
EndIf
Protected count = CountString(ConvertedType," ")
Protected varName.s = StringField( ConvertedType,count+1," ")
If ReturnType
CreateRegularExpression(1,"[\w]+")
varName=ReplaceRegularExpression(1,varName,"result")
EndIf
;TEST : **sfsdfs.EXCUInt
ConvertedType=StringField(ConvertedType,count," ")
If LCase(ConvertedType)="float"
ConvertedType="f"
ElseIf LCase(ConvertedType)="int"
ConvertedType="l"
ElseIf LCase(ConvertedType)="char"
ConvertedType="c"
EndIf
RegisterDllType(ConvertedType)
ProcedureReturn varName+varSuffix+"."+ConvertedType
EndProcedure
Procedure.s GetPBParams(SourceCode.s)
SourceCode=StringField(SourceCode,2,"(")
SourceCode=StringField(SourceCode,1,")")
SourceCode=Trim(SourceCode)
If SourceCode=""
ProcedureReturn ""
EndIf
If SourceCode="void"
ProcedureReturn "()"
EndIf
Protected params.s = ""
Protected count = CountString(SourceCode,",")+1
For i=1 To count
If params<>""
params+","
EndIf
params+GetDllType(StringField(SourceCode,i,","))
Next
ProcedureReturn "("+params+")"
EndProcedure
Procedure GetPBFunctions()
Debug "[ PB Functions ]"
ResetList(DllFunc())
ResetList(DllFuncDECL())
While NextElement(DllFunc()) And NextElement(DllFuncDECL())
CreateRegularExpression(1,"[ \t\w*]+"+DllFunc())
If MatchRegularExpression(1, DllFuncDECL())
Dim Found.s(0)
ExtractRegularExpression(1, DllFuncDECL(), Found.s())
Protected FuncReturn.s = GetDllType(Trim(Found(0)),1)
Protected FuncParams.s = GetPBParams(DllFuncDECL())
If FuncReturn="result.void"
DllFuncDECL()=" "+DllFunc()+FuncParams
Else
DllFuncDECL()=".l "+DllFunc()+FuncParams+" ; "+FuncReturn
EndIf
Debug DllFuncDECL()
Else
MessageRequester("ERROR","RETURNED TYPE NOT FOUND!")
EndIf
Wend
Debug ""
EndProcedure
GetPBFunctions()
; =======================
; get types from text
; =======================
Procedure GetDLLTypes()
Debug "[ PB Types ]"
; =======================
; scan each sourcefile
; =======================
Dim Found.s(0)
ForEach SourceFiles()
Debug "-"+SourceFiles()
Protected text.s = GetSourceTexts(SourceFiles())
If text.s<>""
ResetList(DllTypeDECL())
ResetList(DllType())
While NextElement(DllType()) And NextElement(DllTypeDECL())
If DllTypeDECL()<>""
Continue
EndIf
; =======================
; parse text
; =======================
CreateRegularExpression(1,"typedef[ \t]+[se][\w]+[ \t]+"+DllType()+"[ \t\w]*[{][^}]+[}]")
If Not MatchRegularExpression(1,text)
CreateRegularExpression(1,"typedef[ \t]+[\w]+[ \t]+"+DllType()+"[^;]*")
If Not MatchRegularExpression(1,text)
CreateRegularExpression(1,"typedef[ \t]+[\w]+[ \t*]+[(][*]"+DllType()+"[)][^;]*")
If Not MatchRegularExpression(1,text)
Continue
EndIf
EndIf
EndIf
; =======================
; find type
; =======================
ReDim Found.s(0)
Protected count=ExtractRegularExpression(1,text,Found())
DllTypeDECL()= Found(0)
Debug " >"+ DllTypeDECL()
Wend
EndIf
Next
ResetList(DllTypeDECL())
ResetList(DllType())
While NextElement(DllType()) And NextElement(DllTypeDECL())
If DllTypeDECL()=""
MessageRequester("ERROR","missing functions :"+DllType())
End
EndIf
Wend
Debug ""
EndProcedure
GetDLLTypes()
; i=1
; ForEach TypeReturn()
; Debug "typereturn = "+RemoveString(TypeReturn(),"result.")
; Next
; Debug typeReturnList
;{
If OpenWindow(0, 0, 0, 600, 600, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If CreateGadgetList(WindowID(0))
EditorGadget(1, 10, 10, 580, 580)
EndIf
AddGadgetItem(1,-1,"#ChipmunkDLL=0")
AddGadgetItem(1,-1,"DllFilename$="+#DOUBLEQUOTE$+"chipmunk-4.0.2.dll"+#DOUBLEQUOTE$)
AddGadgetItem(1,-1,"")
AddGadgetItem(1,-1,";OPEN library")
AddGadgetItem(1,-1,"If Not OpenLibrary(#ChipmunkDLL, DllFilename$) : End : EndIf")
AddGadgetItem(1,-1,"If Not IsLibrary(#ChipmunkDLL) : End : EndIf")
AddGadgetItem(1,-1,"")
AddGadgetItem(1,-1,";CLOSE library function")
AddGadgetItem(1,-1,"Procedure FreeChipmunk()")
AddGadgetItem(1,-1," If IsLibrary(#ChipmunkDLL)")
AddGadgetItem(1,-1," CloseLibrary(#ChipmunkDLL)")
AddGadgetItem(1,-1," EndIf")
AddGadgetItem(1,-1,"EndProcedure")
AddGadgetItem(1,-1,"")
;AddGadgetItem(1,-1,";return types")
;ForEach TypeReturn()
;AddGadgetItem(1,-1,"Define.l "+TypeReturn())
;Next
;AddGadgetItem(1,-1,"")
AddGadgetItem(1,-1,";hidden declarations for editor code autocompletion")
AddGadgetItem(1,-1,"CompilerIf 0")
ForEach DllFuncDECL()
AddGadgetItem(1,-1,"ProcedureC"+DllFuncDECL());+"(*x.RECT,y)")
Next
AddGadgetItem(1,-1,"CompilerEndIf")
AddGadgetItem(1,-1,"")
AddGadgetItem(1,-1,";Function prototypes")
ForEach DllFuncDECL()
AddGadgetItem(1,-1,"PrototypeC"+DllFuncDECL());+"(*x.RECT,y)")
Next
AddGadgetItem(1,-1,"")
AddGadgetItem(1,-1,";Function macro")
AddGadgetItem(1,-1,"Macro Quote")
AddGadgetItem(1,-1,#DOUBLEQUOTE$)
AddGadgetItem(1,-1,"EndMacro")
AddGadgetItem(1,-1,"Macro DefineProc(name)")
AddGadgetItem(1,-1,"Global name#.name = GetFunction(#ChipmunkDLL,Quote#name#Quote)")
AddGadgetItem(1,-1,"EndMacro")
AddGadgetItem(1,-1,"")
AddGadgetItem(1,-1,";Function declarations")
ResetList(DllFuncDECL())
ResetList(DllFunc())
While NextElement(DllFuncDECL()) And NextElement(DllFunc())
AddGadgetItem(1,-1,"DefineProc("+DllFunc()+")") ;+","+#DOUBLEQUOTE$+DllFunc()+#DOUBLEQUOTE$
Wend
AddGadgetItem(1,-1,"")
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
EndIf
;}