从LibreOffice Basic调用C共享库函数

我正在尝试从LibreOffice Basic调用C共享库函数,但是当它到达Declare行时,我总是得到“基本运行时错误 . 未实现” . 这只是为了一个有趣的事情,但无法做到这一点是困扰我 .

Declare语句如下所示:

Declare Function score_word Lib "libscrabblescore.so" (ByRef word As String, ByRef bonus As String) As Integer

C函数delaration如下所示:

int score_word(char* word, char* word_bonuses)

(也许ByRef word As String不是char * word的正确翻译?我找不到关于如何将char *参数用于LibreOffice Basic函数的文档 . )

我通过使用Python的ctypes模块调用它来验证共享库本身:

>>> from ctypes import CDLL
>>> lib = CDLL("/usr/lib/libscrabblescore.so")
>>> lib.score_word("qi", "dw dlq")
42
>>>

(所以我有“回答生命,宇宙和一切的终极问题”,而不是在LibreOffice Basic中如何做到这一点!)

我也尝试在Declare语句中使用绝对路径,但没有区别 .

我发现了一个关于调用DLL的主题的Windows线程,其中提问者说他需要将DLL放在特定位置(LibreOffice bin目录),以便LibreOffice可以访问它 . Linux上没有LibreOffice bin目录,不幸的是我的机器上有351个候选目录(我的路径,名称中包含“libreoffice”的所有文件夹或“libreoffice”文件夹下的所有文件夹)名字) .

我尝试了一种霰弹枪方法并在所有351个目录中放置了一个符号链接到共享库,但随后Calc在启动时挂起 . 所以我删除了那些,开始计算,并将它们全部放回原位并尝试了该功能 . 如果它是一个位置的东西,你会认为这将起作用,因为LibreOffice Basic应该在Declare点加载库 . 仍然没有运气 .

在oooforums上有一些看起来很有希望,但是当我尝试查看该主题时,该网站会超时 . (编辑:今晚我设法查看了该主题,这是Windows安全问题 . 我关闭了LibreOffice中的所有宏安全性,但仍然存在问题 . )

那么,有没有人从LibreOffice Basic程序成功调用C共享库函数,该程序知道我做错了什么?谢谢!

回答(2)

2 years ago

乔纳森莱因哈特是正确的;用于调用共享库的“Declare”命令在Windows上实现,但在Linux上不实现 . 由于在博客文章中引用了关于此事的OpenOffice错误报告,我只能验证这一点 .

我第一次尝试解决方案是重写LibreOffice Basic中的函数 . 它工作,但最多需要3秒才能返回结果 .

我考虑放弃并离开它,但是等待三秒钟太不愉快了 . 我研究了如何通过UNO实现一个C函数,这对于一个相当简单的任务来说过于复杂 .

最后我做的是写一个仍然给出“即时”结果的kludge(每个函数调用大约0.025秒) .

我将DLL重写为C控制台应用程序,它接受命令行参数并将结果写入临时文件 . 然后我用一个函数替换了我的LibreOffice Basic代码,该函数使用Shell以阻塞模式调用C控制台应用程序,并从文件中检索结果 . 这很丑陋,但它不是一个多用户的东西,它的工作原理 .

如果有人自己遇到这个问题,这里是我用过的LibreOffice Basic代码 - 这很简单 .

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 years ago

除非您仅限于Basic,否则看起来您的问题已经显示出一个很好的解决方案 . 在Python UNO中写这样的东西:

import ctypes
lib = ctypes.cdll.loadLibrary("/usr/lib/libscrabblescore.so")
result = lib.score_word("qi", "dw dlq")
oText.insertString(oTextCursor, result, 0)