我有一个RCP应用程序(称为RCP-APP)。我创建了一个新的插件(称为插件A),它包装了媒体播放器api(.jar文件)和媒体播放器api通过JNA访问的C库(dll)文件夹。然后我创建了另一个插件(称为插件B),其中包含依赖于插件A的媒体播放器应用程序。
当插件B被激活时,我收到以下错误消息,通知我插件B找不到它正在寻找的媒体播放器.dll:
!ENTRY org.eclipse.jface 4 2 2009-06-22 10:05:22.475 !MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.jface". !STACK 0 java.lang.UnsatisfiedLinkError: Unable to load library 'libvlc': The specified module could not be found. at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:114) at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:157) at com.sun.jna.Library$Handler.(Library.java:123) at com.sun.jna.Native.loadLibrary(Native.java:260) at com.sun.jna.Native.loadLibrary(Native.java:246) at org.videolan.jvlc.internal.LibVlc.(LibVlc.java:41) at org.videolan.jvlc.JVLC.(JVLC.java:45) at com.bah.gs.arts.jekyll.plugins.videolog.VideoLogDisplay.displayStream(VideoLogDisplay.java:32) at com.bah.gs.arts.jekyll.core.extensionpoints.DisplayStreamFactory.getDisplayStreams(DisplayStreamFactory.java:57) at com.bah.gs.arts.jekyll.core.views.medialist.MediaListView$1.doubleClick(MediaListView.java:91) at org.eclipse.jface.viewers.StructuredViewer$1.run(StructuredViewer.java:799) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37) at org.eclipse.core.runtime.Platform.run(Platform.java:880) at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:48) at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) at org.eclipse.jface.viewers.StructuredViewer.fireDoubleClick(StructuredViewer.java:797) at org.eclipse.jface.viewers.AbstractTreeViewer.handleDoubleSelect(AbstractTreeViewer.java:1419) at org.eclipse.jface.viewers.StructuredViewer$4.widgetDefaultSelected(StructuredViewer.java:1173) at org.eclipse.jface.util.OpenStrategy.fireDefaultSelectionEvent(OpenStrategy.java:237) at org.eclipse.jface.util.OpenStrategy.access$0(OpenStrategy.java:234) at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:295) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3823) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3422) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2384) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2348) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2200) at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:495) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:490) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at com.bah.gs.arts.jekyll.core.Application.start(Application.java:20) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504) at org.eclipse.equinox.launcher.Main.run(Main.java:1236) at org.eclipse.equinox.launcher.Main.main(Main.java:1212)
如何通知插件B(或RCP-APP).dll在插件A的特定文件夹中?
似乎api希望通过它的环境PATH变量找到.dll。
我如何实质上传达“插件A /文件夹名称”?
感谢您的协助。
答案 0 :(得分:1)
要访问plugin-a /文件夹中的.DLL文件,您需要访问插件A的Bundle
实例。一种方法是为插件A实现Activator
它至少扩展了Plugin
类(“PluginA
”)。
调用PluginA.getDefault().getBundle().getEntry("folder/some.dll")
将返回.DLL文件的URL。
恕我直言,最好将所有直接访问.DLL文件的代码放入插件A.这样就不需要将插件的内部文件结构暴露给用户了。
答案 1 :(得分:1)
您可能希望查看插件片段;这提供了一种机制,使公众面对Java API与(平台特定的)dll / so文件区别开来。
SWT的包装将是开始研究这类问题的好地方。
答案 2 :(得分:0)
你可以构建一个“二进制”插件,将dll放在子文件夹bin中,然后在清单中确保 *您添加激活器+单件属性。 *您在“构建”,“运行时构建”部分
中检查bin /在包含二进制文件插件的功能中,请务必选中“安装后解压缩插件存档”
在二进制文件插件的激活器中,添加如下内容:
public enum Tool {reach, ctl, ltl};
private static URI toolUri [] = new URI [3];
public static URI getProgramURI(Tool tool) throws IOException {
if (toolUri[tool.ordinal()] == null) {
String relativePath = "bin/its-"+ tool.toString() ;
URL toolff = getDefault().getBundle().getResource(relativePath);
if (toolff == null) {
log.severe("unable to find an executable [" + tool + "] in path " + relativePath);
Enumeration<URL> e = getDefault().getBundle().findEntries("bin/", "*", true);
log.fine("Lising URL available in bin/");
while (e.hasMoreElements()) {
log.finer(e.nextElement().toString());
}
throw new IOException("unable to find the tool binary");
}
URL tmpURL = FileLocator.toFileURL(toolff);
// use of the multi-argument constructor for URI in order to escape appropriately illegal characters
URI uri;
try {
uri = new URI(tmpURL.getProtocol(), tmpURL.getPath(), null);
} catch (URISyntaxException e) {
throw new IOException("Could not create a URI to access the binary tool :", e);
}
toolUri[tool.ordinal()] = uri;
log.fine("Location of the binary : " + toolUri);
File crocExec = new File(uri);
if (!crocExec.setExecutable(true)) {
log.severe("unable to make the command-line tool executable [" + toolUri + "]");
throw new IOException("unable to make the command-line tool executable");
}
}
return toolUri[tool.ordinal()];
}
我从我的一些代码中复制粘贴,很抱歉它与您的DLL示例不完全匹配,我从限制列表中获取可执行路径(请参阅枚举工具)。最后一步(在文件上设置+ x标志)在您的情况下可能没用。另一方面,你可以免费得到一些异常处理代码和缓存:)而且它的测试非常彻底。
它完成你要做的工作,将url传递给二进制文件到下游插件。