Pour l'interface de PBCompiler.exe, voir Library SDK\CompilerInterface.txt (pour la version 4.10 beta)
Voici un bout de code que j'ai utilisé pour me familiariser avec cette nouvelle interface avant de l'intégrer à jaPBe (code PB3.94 [je pense à jaPBe], donc quelques modifications à faire ; avec PB4.xx, il serait plus simple d'utiliser la librairie Process).
Code : Tout sélectionner
;
; //////////////////////////////////////////////
; / PB 4.1x compiler interface /
; //////////////////////////////////////////////
;
;
Global CompilerProcessID, CompilerThreadID ; already in jaPBe
; -----------------------------------------
;
#PB410_PipeMaxLen = 200000
;
Global PB410_InPipeRead.l, PB410_InPipeWrite.l, PB410_OutPipeRead.l, PB410_OutPipeWrite.l, *PB410_Result
Global PB410_ErrorTitle.s, PB410_ErrorFile.s, PB410_ErrorLine.l, PB410_ErrorTitle.s, PB410_ErrorMessage.s
;
*PB410_Result = AllocateMemory(#PB410_PipeMaxLen)
If *PB410_Result = 0
MessageRequester("ERROR", "Cannot allocate memory for pipe")
End
EndIf
;
#PB410_Answer_OutputComplete = "OUTPUT" + #TAB$ + "COMPLETE" + #CRLF$
#PB410_Answer_Ready = #CRLF$ + "READY"
#PB410_Answer_Error = #CRLF$ + "ERROR" + #TAB$
#PB410_Answer_CompileSuccess = "SUCCESS"
#PB410_Answer_Message = "MESSAGE" + #TAB$
#PB410_Answer_IncludeFile = "INCLUDEFILE" + #TAB$
#PB410_Answer_CompileError_Syntax = "ERROR" + #TAB$ + "SYNTAX" + #TAB$
#PB410_Answer_CompileError_Assembler = "ERROR" + #TAB$ + "ASSEMBLER"
#PB410_Answer_CompileError_Linker = "ERROR" + #TAB$ + "LINKER"
#PB410_Answer_CompileError_Resource = "ERROR" + #TAB$ + "RESOURCE"
;
#PB410_Command_End = "END"
#PB410_Command_SourceFile = "SOURCE" + #TAB$
#PB410_Command_TargetFile = "TARGET" + #TAB$
#PB410_Command_ResourceFile = "RESOURCE" + #TAB$
#PB410_Command_IconFile = "ICON" + #TAB$
#PB410_Command_IncludePath = "INCLUDEPATH" + #TAB$
#PB410_Command_Compile = "COMPILE" + #TAB$
;
#PB410_Request_GetStructure = "STRUCTURE" + #TAB$
#PB410_Request_GetInterface = "INTERFACE" + #TAB$
#PB410_Request_GetHelpDirectory = "HELPDIRECTORY" + #TAB$
#PB410_Request_FunctionList = "FUNCTIONLIST"
#PB410_Request_StructureList = "STRUCTURELIST"
#PB410_Request_InterfaceList = "INTERFACELIST"
; Possible COMPILE Flags:
; DEBUGGER - compile with enabled debugger
; INLINEASM - enable InlineASM support
; DLL - create a dll
; XPSKIN - enable XP Skin support (windows only)
; ADMINISTRATOR - request admin mode on vista (windows only)
; USER - request user mode on vista (windows only)
; ONERROR - enable OnError lines support (windows only)
; CONSOLE - create a console mode executable (windows only)
; MMX - create MMX optimitzed exe
; 3DNOW - create 3DNOW optimitzed exe
; SSE - create SSE optimitzed exe
; SSE2 - create SSE2 optimitzed exe
; DYNAMICCPU - create an exe with all processor specific routines
; THREAD - create threadsafe executable
; PROGRESS - indicate compilation progress with 'PROGRESS' responses (see below)
;
Procedure.l PB410_CreatePipes()
Protected ReturnValue.l, security.SECURITY_ATTRIBUTES, lpPipeAttributes.l
;
security\bInheritHandle = 1
;
If GetVersion_() & $FF0000 ; lpPipeAttributes MUST be NUL on Win9x
lpPipeAttributes = @security
EndIf
;
If CreatePipe_(@PB410_InPipeRead, @PB410_InPipeWrite, lpPipeAttributes, 0) = #False
MessageRequester("ERROR", "Cannot create pipe [In]")
Else
If CreatePipe_(@PB410_OutPipeRead, @PB410_OutPipeWrite, lpPipeAttributes, 0) = #False
MessageRequester("ERROR", "Cannot create pipe [Out]")
Else
ReturnValue = #True
EndIf
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure.l PB410_StartCompiler(CompilerEXE$, CompilerFlags.s)
Protected ReturnValue, ProcessInfo.PROCESS_INFORMATION, info.STARTUPINFO
Protected TmpCompilerLine.s, *Cursor, bytesread.l
;
info\cb = SizeOf(STARTUPINFO)
info\dwFlags = #STARTF_USESHOWWINDOW | #STARTF_USESTDHANDLES
info\hStdInput = PB410_OutPipeRead ; read end of our out pipe
info\hStdOutput = PB410_InPipeWrite ; write end of our in pipe
info\wShowWindow = #SW_HIDE ; hide console window
;
CompilerEXE$ + " /STANDBY" + CompilerFlags
;
If CreateProcess_(#Null, @CompilerEXE$, #Null, #Null, #True, 0, #Null, #Null, @info, @ProcessInfo) = #False
CompilerThreadID = 0
CompilerProcessID = 0
;MessageRequester("ERROR", "Cannot create PBCompiler process")
Else
CompilerThreadID = ProcessInfo\hThread
CompilerProcessID = ProcessInfo\hProcess
ReturnValue = #True
EndIf
; Close all handles that we do not need now
;
CloseHandle_(PB410_OutPipeRead)
CloseHandle_(PB410_InPipeWrite)
;
; Wait until ready
*Cursor = *PB410_Result
Repeat
If ReadFile_(PB410_InPipeRead, *Cursor, 1000, @bytesread, #Null) = 0
ReturnValue = #False
Break
Else
*Cursor + bytesread
EndIf
TmpCompilerLine = PeekS(*PB410_Result, *Cursor - *PB410_Result)
Debug TmpCompilerLine
If FindString(TmpCompilerLine, #PB410_Answer_Ready, 1)
Break
EndIf
If FindString(TmpCompilerLine, #PB410_Answer_Error, 1)
ReturnValue = #False
Break
EndIf
ForEver
;
ProcedureReturn ReturnValue
EndProcedure
;
Procedure PB410_IsCompilerActive()
Protected ExitCode.l, bool.l, ReturnValue.l
If CompilerProcessID
bool = GetExitCodeProcess_(CompilerProcessID, @ExitCode)
If ExitCode <> #STILL_ACTIVE Or bool = 0
ReturnValue = #False
CompilerProcessID = #False
Else
ReturnValue = #True
EndIf
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure PB410_KillCompiler()
If CompilerProcessID
TerminateProcess_(CompilerProcessID, 0)
;
CloseHandle_(PB410_InPipeRead)
CloseHandle_(PB410_OutPipeWrite)
CloseHandle_(CompilerProcessID)
CloseHandle_(CompilerThreadID)
;
CompilerProcessID = 0
EndIf
EndProcedure
;
Procedure PB410_InitializeInterface(CompilerEXE$)
Protected ReturnValue.l
If PB410_CreatePipes()
If PB410_StartCompiler(CompilerEXE$, "")
ReturnValue = #True
Else
MessageRequester("ERROR", "Could not create process for PB4.1x compiler interface")
End
EndIf
Else
MessageRequester("ERROR", "Could not create pipes for PB4.1x compiler interface")
End
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure FindMemoryString(*Buffer, BufferLen.l, StringToSearch.s)
Protected ReturnValue.l, LenString.l, *Cursor
LenString = Len(StringToSearch)
If LenString
For *Cursor = *Buffer + BufferLen To *Buffer + LenString Step -1
If CompareMemoryString(*Cursor - LenString, @StringToSearch, 1, LenString) = 0
ReturnValue = *Cursor - *Buffer + 1
Break
EndIf
Next
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure.l PB410_Command(Command.s)
Protected ReturnValue.l, BytesWritten.l
;
Debug "COMMAND : " + Command
If CompilerProcessID
Command + #crlf$
If WriteFile_(PB410_OutPipeWrite, @Command, Len(Command), @BytesWritten, #Null)
ReturnValue = BytesWritten
EndIf
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure.l PB410_Request_SingleLine(Command.s)
Protected ReturnValue.l, TmpCompilerLine.s, *Buffer, *Cursor, bytesread.l, BytesWritten.l
Shared PB410_Request_ReadPosition
PB410_Request_ReadPosition = 0
;
Debug "REQUEST : " + Command
If CompilerProcessID
Command + #crlf$
If WriteFile_(PB410_OutPipeWrite, @Command, Len(Command), @BytesWritten, #Null)
If BytesWritten
*Cursor = *PB410_Result
ReturnValue = #True
Repeat
If ReadFile_(PB410_InPipeRead, *Cursor, 1000, @bytesread, #Null) = 0
MessageRequester("jaPBe", "ReadFile failed on InPipeRead" + Chr(10) + "Increase #PB410_PipeMaxLen in source !", #MB_ICONERROR)
ReturnValue = #False
Break
Else
*Cursor + bytesread
Debug PeekS(*Cursor - bytesread, bytesread)
Debug "COMPLETE"
PokeL(*PB410_Result + bytesread, 0)
Break
EndIf
ForEver
EndIf
EndIf
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure.l PB410_Request(Command.s)
Protected ReturnValue.l, TmpCompilerLine.s, *Buffer, *Cursor, bytesread.l, BytesWritten.l
Shared PB410_Request_ReadPosition
PB410_Request_ReadPosition = 0
;
Debug "REQUEST : " + Command
If CompilerProcessID
Command + #crlf$
If WriteFile_(PB410_OutPipeWrite, @Command, Len(Command), @BytesWritten, #Null)
If BytesWritten
*Cursor = *PB410_Result
ReturnValue = #True
Repeat
If ReadFile_(PB410_InPipeRead, *Cursor, 1000, @bytesread, #Null) = 0
MessageRequester("jaPBe", "ReadFile failed on InPipeRead" + Chr(10) + "Increase #PB410_PipeMaxLen in source !", #MB_ICONERROR)
ReturnValue = #False
Break
Else
*Cursor + bytesread
Debug PeekS(*Cursor - bytesread, bytesread)
EndIf
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_OutputComplete)
If ReturnValue
Debug "COMPLETE"
ReturnValue - Len(#PB410_Answer_OutputComplete) - 1
If PeekS(*PB410_Result + ReturnValue - 2, 2) = #crlf$
ReturnValue - 2
EndIf
Debug "BUFFERLEN = " + Str(ReturnValue)
PokeB(*PB410_Result + ReturnValue, 0)
Break
EndIf
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_Error)
If ReturnValue
Debug "ERROR"
ReturnValue = #False
Break
EndIf
ForEver
EndIf
EndIf
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure PB410_TerminateInterface()
Protected Command.s
If CompilerProcessID
PB410_Command(#PB410_Command_End)
EndIf
; now close all our handles
;
CloseHandle_(PB410_InPipeRead)
CloseHandle_(PB410_OutPipeWrite)
CloseHandle_(CompilerProcessID)
CloseHandle_(CompilerThreadID)
EndProcedure
;
Procedure.s PB410_Request_ReadLine()
Protected length, *pt.BYTE, *endPt, *strPt.BYTE, line.s
Shared PB410_Request_ReadPosition
If PB410_Request_ReadPosition < #PB410_PipeMaxLen
*pt = *PB410_Result + PB410_Request_ReadPosition
*endPt = *PB410_Result + #PB410_PipeMaxLen
*strPt = *pt
While *pt < *endPt
c = *pt\b
*pt = *pt + 1
If c = 0
Break
EndIf
If c = 13
Break
EndIf
If c = 10
Break
EndIf
length = length + 1
Wend
If *pt < *endPt
n = *pt\b
If n + c = 23
*pt = *pt + 1
EndIf
EndIf
PB410_Request_ReadPosition = *pt - *PB410_Result
line = PeekS(*strPt, length)
Else
PB410_Request_ReadPosition = 0
line = ""
EndIf
ProcedureReturn line
EndProcedure
;
Procedure PB410_Compile(CompileFlags.s, SourceFullPath.s, ExecutableFullPath.s, IconFullPath.s, ResourceFullPath.s, IncludeFullPath.s)
Protected Command.s, BytesWritten.l, bytesread.l, ReturnValue.l, *Cursor, ErrorMessage.s, ErrorWasSyntax.l, ErrorTitle.s
Protected ErrorMessagePos.l, IncludeFilePos.l, IncludeFileError.s
If CompilerProcessID = 0
PB410_ErrorLine = 0
PB410_ErrorMessage = "Compiler no ready"
PB410_ErrorTitle = "jaPBe"
ElseIf SourceFullPath = "" Or ExecutableFullPath = ""
PB410_ErrorLine = 0
PB410_ErrorMessage = "Missing compiler parameters"
PB410_ErrorTitle = "jaPBe"
ProcedureReturn #False
Else
; Set compile parameters
PB410_Command(#PB410_Command_SourceFile + SourceFullPath)
PB410_Command(#PB410_Command_TargetFile + ExecutableFullPath)
If IconFullPath
PB410_Command(#PB410_Command_IconFile + IconFullPath)
EndIf
If ResourceFullPath
PB410_Command(#PB410_Command_ResourceFile + ResourceFullPath)
EndIf
If IncludeFullPath
PB410_Command(#PB410_Command_IncludePath + IncludeFullPath)
Else
PB410_Command(#PB410_Command_IncludePath + GetPathPart(SourceFullPath))
EndIf
; Compile !
Command = #PB410_Command_Compile + CompileFlags + #crlf$
If WriteFile_(PB410_OutPipeWrite, @Command, Len(Command), @BytesWritten, #Null)
Debug "BytesWritten = " + Str(BytesWritten)
If BytesWritten
*Cursor = *PB410_Result
Repeat
If ReadFile_(PB410_InPipeRead, *Cursor, #PB410_PipeMaxLen, @bytesread, #Null) = 0
Break
Else
*Cursor + bytesread
EndIf
Debug PeekS(*PB410_Result, *Cursor - *PB410_Result)
; *** COMPILER SUCCESS
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_CompileSuccess)
If ReturnValue
ReturnValue = #True
Break
EndIf
; *** COMPILATION ERROR EVENT
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_CompileError_Syntax)
If ReturnValue
ErrorWasSyntax = #True
ErrorReturnValue = ReturnValue - 1
ErrorTitle = "Syntax error"
EndIf
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_CompileError_Assembler)
If ReturnValue
ErrorReturnValue = ReturnValue - 1
ErrorTitle = "Assembler error"
EndIf
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_CompileError_Linker)
If ReturnValue
ErrorReturnValue = ReturnValue - 1
ErrorTitle = "Linker error"
EndIf
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_CompileError_Resource)
If ReturnValue
ErrorReturnValue = ReturnValue - 1
ErrorTitle = "Resource error"
EndIf
; *** COMPILATION ERROR MESSAGE
ReturnValue = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_OutputComplete)
If ReturnValue
ReturnValue - Len(#PB410_Answer_OutputComplete) - 1
If PeekS(*PB410_Result + ReturnValue - 2, 2) = #crlf$
ReturnValue - 2
EndIf
PokeB(*PB410_Result + ReturnValue, 0)
ErrorMessage = PeekS(*PB410_Result + ErrorReturnValue)
If ErrorWasSyntax
PB410_ErrorLine = Val(StringField(ErrorMessage, 1, #TAB$))
PB410_ErrorFile = SourceFullPath
; Error in included file ?
IncludeFilePos = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_IncludeFile)
If IncludeFilePos
IncludeFileError = PeekS(*PB410_Result + IncludeFilePos - 1)
PB410_ErrorLine = Val(StringField(IncludeFileError, 2, #TAB$))
PB410_ErrorFile = StringField(IncludeFileError, 1, #TAB$)
Debug PB410_ErrorFile + " : " + Str(PB410_ErrorLine)
EndIf
PB410_ErrorTitle = ErrorTitle
; Error message
ErrorMessagePos = FindMemoryString(*PB410_Result, *Cursor - *PB410_Result, #PB410_Answer_Message)
If ErrorMessagePos
PB410_ErrorMessage = PeekS(*PB410_Result + ErrorMessagePos - 1)
PB410_ErrorMessage = StringField(PB410_ErrorMessage, 1, #crlf$)
EndIf
Else
PB410_ErrorLine = 0
PB410_ErrorMessage = ErrorMessage
PB410_ErrorTitle = ErrorTitle
EndIf
ReturnValue = #False
Break
EndIf
ForEver
EndIf
EndIf
EndIf
ProcedureReturn ReturnValue
EndProcedure
;
Procedure PB410_DisplayCompileError()
If PB410_ErrorLine
MessageRequester(PB410_ErrorTitle, "File : " + PB410_ErrorFile + Chr(10) + "Line : " + Str( PB410_ErrorLine) + Chr(10) + Chr(10) + PB410_ErrorMessage, #MB_ICONERROR)
Else
MessageRequester(PB410_ErrorTitle, PB410_ErrorMessage, #MB_ICONERROR)
EndIf
EndProcedure
;
;
;
; ///////////////////////////////// TEST ///////////////////////////////////
;
;
;
CompilerEXE$ = "c:\PureBasic410\Compilers\PBCompiler.exe"
;
Debug "Initializing ...."
PB410_InitializeInterface(CompilerEXE$)
Debug "... done"
;
;
Debug PB410_IsCompilerActive()
;
;
;
; CompileFlags.s = "DEBUGGER"
; CompileFlags.s = ""
; SourceFullPath.s = "C:\PureBasic410\Program\TEST2.pb"
; ExecutableFullPath.s = SourceFullPath + ".exe"
; IconFullPath.s = ""
; ResourceFullPath.s = ""
; IncludeFullPath.s = ""
; If PB410_Compile(CompileFlags.s, SourceFullPath.s, ExecutableFullPath.s, IconFullPath.s, ResourceFullPath.s, IncludeFullPath.s)
; MessageRequester("YES", "Success !")
; Else
; PB410_DisplayCompileError()
; EndIf
Command.s = #PB410_Request_GetHelpDirectory + "CloseFile"
LenResult = PB410_Request_SingleLine(Command.s)
If LenResult
; MessageRequester("Result", PeekS(*PB410_Result, LenResult))
Debug "-----------------"
Repeat
a$ = PB410_Request_ReadLine()
Debug a$
Until a$ = ""
Debug "-----------------"
EndIf
Command.s = "INTERFACELIST" + #CRLF$
LenResult = PB410_Request(Command.s)
If LenResult
If CreateFile(0, "c:\PureBasic410\Program\result.txt")
WriteData(*PB410_Result, LenResult)
CloseFile(0)
EndIf
; MessageRequester("Result", PeekS(*PB410_Result, LenResult))
Debug "-----------------"
Repeat
a$ = PB410_Request_ReadLine()
Debug a$
Until a$ = ""
Debug "-----------------"
EndIf
;
;
; Write our command to the compiler
;
; Command.s = #PB410_Request_GetStructure + "STARTUPINFO"
; ;Command.s = "invalid stuff"
; LenResult = PB410_Request(Command.s)
; If LenResult
; Debug "-----------------"
; Repeat
; a$ = PB410_Request_ReadLine()
; Debug a$
; Until a$ = ""
; Debug "-----------------"
; EndIf
Command.s = #PB410_Request_GetStructure + "RECT"
LenResult = PB410_Request(Command.s)
If LenResult
; MessageRequester("Result", PeekS(*PB410_Result, LenResult))
Debug "-----------------"
Repeat
a$ = PB410_Request_ReadLine()
Debug a$
Until a$ = ""
Debug "-----------------"
EndIf
;
; tell the compiler to shut down
;
TheEnd:
PB410_TerminateInterface()
;
;
Debug PB410_IsCompilerActive()
;
;
End