Calling C shared library function from LibreOffice Basic

丶灬走出姿态 提交于 2019-12-02 18:24:33

问题


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!


回答1:


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



回答2:


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!