Valentina with PureBasic

PureBasic is a procedural programming language and IDE based on BASIC, for Windows, Linux and macOS. It allows the developer to open a shared library in order that the functions within it may be accessed. This allows the use of Valentina ADK for C (VCSDK) inside of PureBasic applications, so that Valentina Database and Valentina Reports engines are usable in PureBasic development.

Providing Shared C libraries in the form of a Valentina ADK is one way Paradigma Software makes Valentina accessible to more developers. There are also numerous native ADKs available (.net, Java and others) and Valentina Server (which incorporates Valentina DB Server, Valentina Reports Server, and Valentina SQLite Server) also supports REST.

Before use in the PureBasic code, each necessary C function needs to be wrapped with the native PureBasic procedure and enumerations redeclared.

Declare Enumerations

As an entry point to use the VCSDK library this constant is declared:

Enumeration
  #VCSDK
EndEnumeration

All necessary Valentina enumerations are redeclared, for example:

Enumeration EVReportPrintType
  #kToUnknown
  #kToMetafile
  #kToPostscript
  #kToPDF
  #kToHTML
  #kToLatex
  #kToSVG
  #kToPicture_GIF  = 100
  #kToPicture_JPG  = 101
  #kToPicture_PNG  = 102
  #kToPicture_TIFF = 103
  #kToPicture_BMP  = 104  
EndEnumeration

Wrap Functions

The VCSDK uses UTF-8-encoded NUL-terminated strings, so each string argument should be converted into the appropriate form before passing to the library using the UTF8 procedure.

All Valentina-based applications have to initialize the library using:

  • Valentina_Init for the purposes of working with Valentina Databases

AND/OR

  • Valentina_InitReports for the purposes of working with the Valentina Reports engine

So these functions must be wrapped first:

Procedure Valentina_Init( inCacheSize.i = 10 * 1024 * 1024, inMacSN.s = "", inWinSN.s = "", inUnixSN.s = "" )
 
  *bMacSN  = UTF8( inMacSN  )
  *bWinSN  = UTF8( inWinSN  )
  *bUnixSN = UTF8( inUnixSN )
 
  CallFunction( #VCSDK, "Valentina_Init", inCacheSize, *bMacSN, *bWinSN, *bUnixSN )
 
  FreeMemory( *bMacSN  )
  FreeMemory( *bWinSN  )
  FreeMemory( *bUnixSN )
 
EndProcedure
 
Procedure Valentina_InitReports( inMacSN.s = "", inWinSN.s = "", inUnixSN.s = "" )
 
  *bMacSN  = UTF8( inMacSN  )
  *bWinSN  = UTF8( inWinSN  )
  *bUnixSN = UTF8( inUnixSN )
 
  CallFunction( #VCSDK, "Valentina_InitReports", *bMacSN, *bWinSN, *bUnixSN )
 
  FreeMemory( *bMacSN  )
  FreeMemory( *bWinSN  )
  FreeMemory( *bUnixSN )
 
EndProcedure

After the work with the library is finished it is necessary to call one or both shutdown-functions - Valentina_Shutdown or Valentina_ShutdownReports.

So these functions should be wrapped as well.

Procedure Valentina_Shutdown()
  CallFunction( #VCSDK, "Valentina_Shutdown" )
EndProcedure
 
Procedure Valentina_ShutdownReports()
  CallFunction( #VCSDK, "Valentina_ShutdownReports" )
EndProcedure

The next step is to wrap all necessary functions depending on the use in the application - to work with databases, projects, and reports.

Here's the set of procedures required to generate a report:

Procedure.i Project_New( inProjectLocation.s )
 
  *bProjectLocation = UTF8( inProjectLocation )
 
  res.i = CallFunction( #VCSDK,"Project_New", *bProjectLocation )
 
  FreeMemory( *bProjectLocation )
 
  ProcedureReturn res
 
EndProcedure
 
Procedure.i Project_Open( inProject.i )
  CallFunction( #VCSDK, "Project_Open", inProject )
EndProcedure
 
Procedure Project_Close( inProject.i )
  CallFunction( #VCSDK, "Project_Close", inProject )
EndProcedure
 
Procedure.i Project_MakeNewReportByNameWithDatasource( inProject.i, inName.s, inDatasource.s, inQuery.s )
 
  *bName       = UTF8( inName       )
  *bDatasource = UTF8( inDatasource )
  *bQuery      = UTF8( inQuery      )
 
  res = CallFunction( #VCSDK, "Project_MakeNewReportByNameWithDatasource", inProject, *bName, *bDatasource, *bQuery )
 
  FreeMemory( *bName       )
  FreeMemory( *bDatasource )
  FreeMemory( *bQuery      )
 
  ProcedureReturn res
 
EndProcedure
 
Procedure Report_PrintToDisk( inReport.i, inLocation.s, inFormat.i, inFromPage.i = 1, inToPage.i = 0 )
 
  *bLocation = UTF8( inLocation )
 
  CallFunction( #VCSDK,"Report_PrintToDisk", inReport, *bLocation, inFormat, inFromPage, inToPage )
 
  FreeMemory( *bLocation )
 
EndProcedure

After finishing the work with VCSDK resources (like remote connection, project, report), it is necessary to release them. Each resource that can be freed has an appropriate ResourceType_Free function. These functions need to be wrapped for proper memory management.

Procedure Project_Free( inProject.i )
  CallFunction( #VCSDK, "Project_Free", inProject )
EndProcedure
 
Procedure Report_Free( inReport.i )
  CallFunction( #VCSDK, "Report_Free", inReport )
EndProcedure

All previous enumerations and procedures can be saved in the separate file (for example, Valentina.pb) so it will be easy to reuse them in different applications.

PureBasic Reports Application

Let's write a PureBasic application which uses the Valentina Reports engine. The project file, datasource database and VCSDK library are placed near to PureBasic sources.

  • Include the Valentina definitions:
XIncludeFile "Valentina.pb"
  • Find the path to the library. On different operating systems, the VCSDK library name is different, so it is necessary to use conditional compilation, for example:
CompilerSelect #PB_Compiler_OS
 
  CompilerCase #PB_OS_Windows
    vcsdk_path.s = "vcsdk_release_x64.dll"
 
  CompilerCase #PB_OS_Linux
    vcsdk_path.s = "libVCSDK.so"
 
  CompilerCase #PB_OS_MacOS
    vcsdk_path.s = "vcsdk_x64.dylib"
 
CompilerEndSelect
  • Open the library:
If Not OpenLibrary( #VCSDK, vcsdk_path )
  Debug "Could not open VCSDK library"
  End
EndIf
  • Init the Valentina Reports engine:
Valentina_InitReports()
  • Open the project:
project.i = Project_New( "reports.vsp" )
Project_Open( project )
  • Generate a report:
datasource.s = "sqlite://reports_db.sqlite"
 
report.i = Project_MakeNewReportByNameWithDatasource( project, "Report_1", datasource, "SELECT * FROM T1" )
  • Print generated report to the PDF file on disk:
Report_PrintToDisk( report, "report.pdf", #kToPDF )
  • Shutdown the Valentina Reports engine and close the library:
Valentina_ShutdownReports()
CloseLibrary( #VCSDK )

Complete application you can find here

Are you a PureBasic user? Please share your comments on this tutorial and on usage of Valentina with PureBasic on our open forums, so we can improve the quality of this tutorial.