Thursday 20 October 2016

How to use C code via FBSL inside ABAP

The actual release candidate of Freestyle BASIC Script Language (FBSL) integrates a dynamic C JIT compiler, so is it possible to use ANSI C code inside FBSL. And with FBSLX, a COM library, you can use FBSL inside ABAP.

Here an example how to use ANSI C inside ABAP.

"-Begin-----------------------------------------------------------------
  Program zCMandelbrot.

    "-Constants---------------------------------------------------------
      Constants CrLf(2) Type c Value %_CR_LF.
      Constants SW_SHOWNORMAL Type i Value 1.
      Constants FbslFileName Type String Value 'zCMandelbrot.fbs'.

    "-Variables---------------------------------------------------------
      Data oFBSL Type OLE2_OBJECT.
      Data Buffer Type String Value ''.
      Data WorkDir Type String Value ''.
      Data WinInc Type String Value ''.
      Data FileName Type String Value ''.
      Data ProcID Type i Value 0.
      Data rc Type i.

    "-Macros------------------------------------------------------------
      Define _.
        Concatenate Buffer &1 CrLf Into Buffer.
      End-Of-Definition.

      Define Flush.
        Call Function 'AC_SYSTEM_FLUSH' Exceptions Others = 1.
      End-Of-Definition.

    "-Main--------------------------------------------------------------
      Create Object oFBSL 'FbslX'.
      If sy-subrc <> 0 Or  oFBSL-Handle = 0 Or oFBSL-Type <> 'OLE2'.
        Call Function 'ZFBSL_DLL'.
        Create Object oFBSL 'FbslX'.
      EndIf.

      If sy-subrc = 0 And oFBSL-Handle > 0 And oFBSL-Type = 'OLE2'.

        Call Method Of oFBSL 'About'.

        Call Method cl_gui_frontend_services=>get_sapgui_workdir
          Changing SAPWORKDIR = WorkDir Exceptions Others = 1.

        Call Method Of oFBSL 'ExtractFbslExe'.

"-FBSL script begin-----------------------------------------------------
_ 'Dim MaxIter = 50'.
_ 'Dim XRes As Integer'.
_ 'Dim YRes As Integer'.
_ 'Dim colors[MaxIter] As Integer'.

_ 'FBSLSETTEXT(Me, "DynC Mandelbrot Benchmark")'.
_ 'RESIZE(Me, 0, 0, 400, 400)'.
_ 'SHOW(Me)'.

_ 'FillColorTable()'.
_ 'FBSL.GETCLIENTRECT(ME, 0, 0, XRes, YRes)'.

_ 'Dim hdc = GetDC(ME)'.
_ 'Dim t = GetTickCount()'.

_ 'GenMandelbrot(-2.1, -1.25, 0.6, 1.25, XRes, YRes, MaxIter, hDC, _'.
_ '  @colors[0])'.

_ 'MSGBOX(, GetTickCount() - t & " ticks", "FBSL",)'.
_ 'ReleaseDC(ME, hdc)'.

  "-Dynamic C routine begin---------------------------------------------
_ 'DynC GenMandelbrot(!!xMn, !!yMn, !!xMx, !!yMx, %xr, %yr, %mitrs, _'.
_ '  %dc, %clr)'.

    "-ANSI C begin------------------------------------------------------
    "-
    "- You can store this code block in an include
    "-
    "-------------------------------------------------------------------

_ '  void __attribute__((stdcall)) SetPixel(int, int, int, int);'.

_ '  int Iterate(double cx, double cy, int MaxIter)'.
_ '  {'.
_ '    int iters = 0;'.
_ '    double X = cx, Y = cy, X2 = X * X, Y2 = Y * Y;'.
_ '    double temp;'.

_ '    while (iters++ < MaxIter && X2 + Y2 < 4) {'.
_ '      temp = cx + X2 - Y2;'.
_ '      Y = cy + 2 * X * Y;'.
_ '      Y2 = Y * Y;'.
_ '      X = temp;'.
_ '      X2 = X * X;'.
_ '    }'.

_ '    return iters;'.
_ '  }'.

_ '  void main(double xMn, double yMn, double xMx, double yMx, '.
_ '    int XRes, int YRes, int MaxIter, int hDC, int* colors[])'.
_ '  {'.
_ '    int iX, iY, iters;'.
_ '    double cx, cy;'.
_ '    double dx = (xMx - xMn) / (XRes - 1);'.
_ '    double dy = (yMx - yMn) / (YRes - 1);'.

_ '    for (iY = 0; iY < YRes; iY++) {'.
_ '      cy = yMn + iY * dy;'.
_ '      for (iX = 0; iX < XRes; iX++) {'.
_ '        cx = xMn + iX * dx;'.
_ '        iters = Iterate(cx, cy, MaxIter);'.
_ '        if (iters == MaxIter)'.
_ '          SetPixel(hDC, iX, iY, 0);'.
_ '        else'.
_ '          SetPixel(hDC, iX, iY, (int)colors[iters]);'.
_ '      }'.
_ '    }'.

_ '  }'.

    "-ANSI C end--------------------------------------------------------

_ 'End DynC'.
  "-Dynamic C routine end-----------------------------------------------

_ 'SUB FillColorTable()'.
_ '  DIM r, g, b'.
_ '  DIM rd, gd, bd'.
_ '  DIM rr, gg, bb'.
_ '  DIM i, j, wid'.

_ '  DIM clr[3]'.
_ '  clr[1] = RGB(0, 255, 0)'.
_ '  clr[2] = RGB(255, 255, 0)'.
_ '  clr[3] = RGB(255, 0, 0)'.

_ '  wid = MaxIter / 3'.

_ '  FOR j = 0 TO 2'.
_ '    toRGB(clr[j], r, g, b)'.
_ '    toRGB(clr[j + 1], rr, gg, bb)'.
_ '    rd = (rr - r) / (wid + 1)'.
_ '    gd = (gg - g) / (wid + 1)'.
_ '    bd = (bb - b) / (wid + 1)'.
_ '    FOR i = 0 TO wid'.
_ '      colors[j * wid + i] = RGB(r, g, b)'.
_ '      r = r + rd'.
_ '      g = g + gd'.
_ '      b = b + bd'.
_ '    NEXT'.
_ '  NEXT'.
_ 'END SUB'.

_ 'SUB toRGB(c, r, g, b)'.
_ '  r = c BAND &HFF'.
_ '  g = (c BAND &HFF00) / &H100'.
_ '  b = (c BAND &HFF0000) / &H10000'.
_ 'END SUB'.

"-FBSL script end-------------------------------------------------------

        Concatenate WorkDir '\' FbslFileName Into FileName.
        Call Method Of oFBSL 'WriteFile' Exporting #1 = FileName
          #2 = Buffer.
        Flush.

        Call Method Of oFBSL 'Shell' = ProcID Exporting
          #1 = 'Fbsl.exe' #2 = FbslFileName #3 = SW_SHOWNORMAL #4 = 1.
        Flush.

        Call Method Of oFBSL 'DeleteFile' Exporting #1 = FileName.
        Call Method Of oFBSL 'DeleteFile' Exporting #1 = 'Fbsl.exe'.

        Free Object oFBSL.
      EndIf.

"-End-------------------------------------------------------------------

How to use C code via FBSL inside ABAP

You can store your C code in an include file and on this way you have an own C style code block inside your ABAP code.

In the message box you see the count of ticks (484) to generate the mandelbrot graphic. If you use the FBSL program, you need more ticks (2752).

No comments:

Post a Comment