VBA, external C dll/so (shared library) not in memory

asked 2020-01-14 10:38:06 +0100

gecos gravatar image

updated 2020-01-14 12:57:53 +0100

I have a simple C dll (shared library, multi-threaded) which stores (as static data) some value to share between methods mytestA, mytestB , this library works fine with Excel (Excel loads once the dll and doesn't release it) while LibreOffice reloads / releases the dll every time I call a method in dll

Public Declare Function mytestA Lib "test.dll" (ByVal a As Long) As Long

Public Declare Function mytestB Lib "test.dll" (ByVal b As Long) As Long

c = mytestA(a)

d = mytestB(b)

this means that I cannot share (via test.dll) data between mytestA, mytestB,

can you suggest a way to avoid this problem (i.e. how to instruct Basic intepreter to do not release test.dll when interpreting VBA but keep the same instance) ?

edit retag flag offensive close merge delete

Comments

You already have been pointed to preformatted text functionality is on purpose. Please support potential readers of your post and unburden reading through its use.

Opaque gravatar imageOpaque ( 2020-01-14 10:49:59 +0100 )edit

That would need an enhancement request, with a clear specification what is expected... do you expect the DLL to be loaded during Basic program run (i.e., being unloaded after macro finishes?) during the whole LO session (with implications like never unloading when quicklaunch is active)?

Mike Kaganski gravatar imageMike Kaganski ( 2020-01-14 13:46:51 +0100 )edit

Mike, does the intepreter, in present version, create an instance of shared library when running each macro ? According my tests it would seem that there is not a unique instance (per thread / process) as Excel do, I am not an expert with LibreOffice so pardon me if the question may appear stupid, maybe I just need to adopt a different way to load/call the external library to force some sort of "static" load (i.e. the same instance in memory untill the application ends)

gecos gravatar imagegecos ( 2020-01-14 13:53:34 +0100 )edit

There's no "static" mode currently; the handles to DLLs are kept in SbiDllMgr, which is disposed in the end of execution of top-level Basic method in SbModule::Run.

I only could think of a hack where you use LoadLibrary API to increment use count of your DLL, which would prevent its unloading when the manager is disposed. Again: LibreOffice is a monolythic process, with all components and all documents sharing common state and address space. Loading a DLL and not releasing it could hold it loaded until the last LO module is closed - which, in case of already mentioned quicklaunch, could be indeterminate.

Mike Kaganski gravatar imageMike Kaganski ( 2020-01-14 14:13:46 +0100 )edit

actually i am converting a few xls pages (including VBA to access external library) , do you know if there is a way (I mean the possibility to code via BASIC / VBA inside the xls page) to avoid library unloading ? The optimal scope would be to keep the same instance untill the application ends but of course I can consider alternatives for Windows and Linux, thanks for your help

gecos gravatar imagegecos ( 2020-01-14 14:22:13 +0100 )edit

I seem to already mentioned that you could use a hack involving LoadLibrary call...

Private Declare Function LoadLibraryA Lib "kernel32" (str) As Long
...
' somewhere in the macro code - enough to call once per LO session '
LoadLibraryA("C:\path\to\test.dll")

Note that LO marshals strings as char*, not wchar_t*; so you would either use LoadLibraryA, or prepare an array of Integers and fill manually to pass a Unicode string to LoadLibraryW.

Mike Kaganski gravatar imageMike Kaganski ( 2020-01-14 14:39:35 +0100 )edit

thanks, at last I decided to adapt the code including a simple test on a global var, now MyTest() macro (LibreOffice BASIC) looks like

Private Declare Function LoadLibrary Lib "kernel32" alias "LoadLibraryA" (ByVal lpLibName As String) As Long
Global LibLoad  As Long 


Sub MyTest()

if  LibLoad = 0 then
         LoadLibrary("test.dll")
         LibLoad = 1
endif

' my code here

End Sub

Hoping that this problem will be solved in some new release of LibreOffice....

gecos gravatar imagegecos ( 2020-01-14 15:29:01 +0100 )edit

Hoping that this problem will be solved in some new release of LibreOffice....

Definitely not, unless there is a feature request I mentioned above.

And even with that request, I suppose, I wouldn't hold my breath: there is too much downside in keeping DLLs loaded without a hope to unload until the whole suite is unloaded. If needed, a native extension fits this task better; in the end, the mentioned workaround is enough.

Mike Kaganski gravatar imageMike Kaganski ( 2020-01-14 19:48:21 +0100 )edit

I can't comment about LibreOffice development, however considering the huge amount of xls/vba pages/applications created and the (now) limited (or no) support (see Linux) from Microsoft, there should be room for improvements... anyway, do you know if LibreOffice (Linux version) allows (see Windows version) to code

Private Declare Function mytest Lib "test.so" (ByVal p As Long) As Long

translating to dlopen() or equivalent system call ? Do the Linux version require different code ? The same doubt for LoadLibrary (see my previous comment), should I call (from LibreOffice BASIC) dlopen (or equivalent) ? I am unable to locate a detailed description of all BASIC keyworks and code allowed in the different versions of LibreOffice, thanks for help.

gecos gravatar imagegecos ( 2020-01-16 20:23:50 +0100 )edit