https://bugs.documentfoundation.org/show_bug.cgi?id=147377

            Bug ID: 147377
           Summary: Reimplement SbiDllMgr::Call using libffi
           Product: LibreOffice
           Version: unspecified
          Hardware: All
                OS: All
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: medium
         Component: BASIC
          Assignee: [email protected]
          Reporter: [email protected]
                CC: [email protected], [email protected]

Currently Basic's Declare statement [1] is implemented in
basic/source/runtime/dllmgr*.cxx using home-grown marshaling code [2]. This
poses several problems:

1. The code is platform-specific (requires separate maintenance per platform),
with much duplication.
2. It has limitation to 20 arguments (see [3]).
3. Calls using non-default calling convention are not implemented (and would
require much work) - so e.g. CDecl keyword is not implemented on Win32, where
it makes sense.

There is libffi [4] that solves exactly this problem. Using it instead of
home-grown code to call external DLL functions would allow to unify the code
across platforms (and implement it where it isn't implemented); avoid any
argument count limitations; define calling convention.

The library uses MIT license; it is already used in LO codebase (it is a
requirement for Python), so it only needs to be linked to Library_sb to be
usable there. Then the code could look similar to

>   std::vector<ffi_type*>arg_types;
>   std::vector<void*>arg_values;
>   std::vector<char> blob;
>   if (arguments)
>   {
>       arg_types.reserve(arguments->Count());
>       arg_values.reserve(arguments->Count());
>       blob.reserve(arguments->Count() * 8);
>
>       for (sal_uInt32 i = 1; i < arguments->Count(); ++i)
>       {
>           // Put argument values to blob, store pointers to them
>           // in arg_values, and their types in arg_types
>       }
>   }
>
>   ffi_type* ret_t = SbxDataType_to_ffi_type(result.GetType());
>   ffi_abi eAbi = GetAbi(); // e.g., FFI_DEFAULT_ABI or FFI_MS_CDECL
>
>   // Prepare the ffi_cif structure.
>   ffi_cif cif;
>   if (ffi_status status = ffi_prep_cif(&cif, eAbi, 2, ret_t, 
> arg_types.data());
>       status != FFI_OK)
>   {
>       // Handle the ffi_status error.
>   }
>
>   // Invoke the function.
>   ffi_arg retval;
>   ffi_call(&cif, FFI_FN(proc.proc), &retval, arg_values.data());
>   // ...

(sketched after [5]).

[1] https://help.libreoffice.org/latest/en-US/text/sbasic/shared/03090403.html
[2]
https://opengrok.libreoffice.org/search?&defs=SbiDllMgr%3A%3ACall&project=core
[3]
https://ask.libreoffice.org/t/passing-arrays-in-basic-works-with-excel-error-73-in-libreoffice/48267
[4] https://sourceware.org/libffi/
[5] https://linux.die.net/man/3/ffi_call

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to