I'm trying to call a C shared library function from LibreOffice Basic, but I always get "Basic Runtime Error. Not implemented" when it hits the Declare line. It's just for a fun thing but being unable to do it is bugging me.
The Declare statement looks like this:
Declare Function score_word Lib "libscrabblescore.so" (ByRef word As String, ByRef bonus As String) As Integer
The C function delaration looks like this:
int score_word(char* word, char* word_bonuses)
(Maybe ByRef word As String is not the right translation of char* word? I can't find documentation on how to use char* parameters to functions from LibreOffice Basic.)
I validated the shared library itself by calling it using Python's ctypes module:
>>> from ctypes import CDLL
>>> lib = CDLL("/usr/lib/libscrabblescore.so")
>>> lib.score_word("qi", "dw dlq")
42
>>>
(So I have the "Answer to the Ultimate Question of Life, the Universe, and Everything," just not for how to do this in LibreOffice Basic!)
I tried using the absolute path in the Declare statement as well, and it made no difference.
I found a Windows thread on the topic of calling DLL's where the asker said he needed to put the DLL in a specific location (the LibreOffice bin directory) so LibreOffice could access it. There is no LibreOffice bin directory per-se on Linux, and unfortunately there are 351 candidate directories I was able to identify on my machine (my path, and all folders with "libreoffice" in the name or under a folder with "libreoffice" in the name).
I tried a shotgun approach and put a symbolic link to the shared library in all 351 directories, but then Calc hangs on startup. So I removed those, started Calc, and put them all back in place and tried the function. If it was a location thing, you'd think that would work as LibreOffice Basic is supposed to load the library at the point of the Declare. Still no luck.
There was something that looked promising on oooforums but the site times out when I try to view the thread. (EDIT: I managed to view the thread this evening and it was Windows security problem. I turned off all macro security in my LibreOffice and still have the problem.)
So, has anybody ever successfully called a C shared library function from a LibreOffice Basic program that knows what I'm doing wrong? Thanks!
Jonathon Reinhart is correct; the "Declare" command for calling shared libraries is implemented on Windows but not on Linux. I was only able to verify this because of a reference to an OpenOffice bug report on the matter on a blog post.
My first attempt at a solution was to rewrite the function in LibreOffice Basic. It worked, but would take up to 3 seconds to return its results.
I considered giving up and leaving it like that, but it was too unpleasant to have a three second wait. I looked into how to implement a C++ function through UNO, which was overly complex for a fairly trivial task.
Finally what I did was to write a kludge that still gives "instant" results (around 0.025 seconds each function call).
I rewrote the DLL as a C++ console app that takes command line arguments and writes the result to a temp file. Then I replaced my LibreOffice Basic code with a function that calls the C++ console app in blocking mode using Shell and retrieves the results from the file. It's ugly, but it's not a multi-user thing and it works.
In case anyone stumbles across this issue themselves, here's the LibreOffice Basic code I used to do this--it's very simple.
option explicit
function scorewords(wordlist as string, bonuslist as string) as integer
dim cparams as string
dim fileno as integer
dim results_file as string
dim score as integer
if wordlist = "" then
scorewords = 0
exit function
end if
cparams = """" + wordlist + """" + " " + """" + bonuslist + """"
results_file = "/tmp/scrabblescore.dat"
Shell("/usr/bin/getscrabblescore", 6, cparams, true)
fileno = freefile
open results_file for input as fileno
input #fileno, score
close #fileno
kill results_file
scorewords = score
end function
Unless you are limited to Basic then it looks like your question already shows a good solution. Write something like this in Python UNO:
import ctypes
lib = ctypes.cdll.loadLibrary("/usr/lib/libscrabblescore.so")
result = lib.score_word("qi", "dw dlq")
oText.insertString(oTextCursor, result, 0)
来源:https://stackoverflow.com/questions/24353919/calling-c-shared-library-function-from-libreoffice-basic