1

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

Declare 语句如下所示:

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

C 函数声明如下所示:

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 在启动时挂起。所以我删除了这些,启动了 Calc,然后将它们全部放回原处并尝试了该功能。如果这是一个位置问题,您会认为 LibreOffice Basic 应该在声明点加载库。仍然没有运气。

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

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

4

2 回答 2

1

乔纳森·莱因哈特是正确的;用于调用共享库的“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
于 2014-07-04T13:11:09.620 回答
0

除非您仅限于 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)
于 2015-09-17T19:42:36.077 回答