首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNA可以用于像IMAPI这样复杂的Windows吗?

JNA可以用于像IMAPI这样复杂的Windows吗?
EN

Stack Overflow用户
提问于 2021-11-25 10:46:14
回答 1查看 164关注 0票数 2

我设法让COM4J在windows中使用了一些功能(CD写入)。

但是,我没有让任何返回SAFEARRAY的调用正常工作,但是这个项目目前似乎没有活动.

DLL通常位于C:\Windows\System32 32\imapi2.dll中,使用它还需要使用C:\Windows\System32\imapi2fs.dll

环顾四周,寻找一个活跃的JAVA桥项目,我来到了JNA。

简化JAVA-COM桥接项目的任务引起了我的兴趣.然而,我在第一个障碍上摔倒了,我希望有人能帮助我。

到目前为止,我已经学习了Microsoft示例并编写了一个Powershell应用程序,我从该应用程序中调用了一系列需要对API.CDInterface进行的调用

使用IMAPI需要做的第一件事是创建一个IDiskMaster2实例,所以我已经通过Imapi2接口声明了这一点,如下所示

代码语言:javascript
复制
public interface Imapi2 extends Library {
        Imapi2 INSTANCE = (Imapi2)
                Native.load("C:/Windows/System32/imapi2.dll" , Imapi2.class);

        public static class IDiscMaster2 extends Structure {
            int getCount;

            public int getCount() {
                return getCount;
            }
        }
        IDiscMaster2 createMsftDiscMaster2();
    }

然后在主代码中

代码语言:javascript
复制
 Imapi2.IDiscMaster2 recorderList = Imapi2.INSTANCE.createMsftDiscMaster2();
        System.out.println("Found " + recorderList.getCount() + " Recorders");

在对Native.load()的调用中添加‘Native.load’也不起作用。

我猜我做了一些根本错误的事情,但还不清楚如何让JNA‘看到’一个新的dll你想要接口……而且,我还有点担心这个API与人们使用JNA交谈的API有很大的不同,所以可能不值得尝试!

代码语言:javascript
复制
public interface Imapi2 extends Library {
        Imapi2 INSTANCE = (Imapi2)
                Native.load("C:/Windows/System32/imapi2.dll" , Imapi2.class);

        public class IDiscMaster2 extends Dispatch {

            public static final CLSID CLSID_MsftDiscMaster2 = new CLSID("2735412F-7F64-5B0F-8F00-5D77AFBE261E");

            public IDiscMaster2() {
            }

            private IDiscMaster2(Pointer pvInstance) {
                super(pvInstance);
            }

            public static IDiscMaster2 create() {
                PointerByReference pbr = new PointerByReference();

                WinNT.HRESULT hres = Ole32.INSTANCE.CoCreateInstance(CLSID_MsftDiscMaster2, null, WTypes.CLSCTX_ALL, null, pbr);
                if (COMUtils.FAILED(hres)) {
                    System.out.println("ERROR: Failed to create instance");
                    return null;
                }

                return new IDiscMaster2(pbr.getValue());
            }

            public WinNT.HRESULT _getCount(Pointer count ){
                return (WinNT.HRESULT) _invokeNativeObject(2, new Object[]{count}, WinNT.HRESULT.class);
            }

            public long getCount() {
                try {
                    long count = -1;
                    Pointer ptr = new Pointer(count);
                    WinNT.HRESULT result = _getCount(ptr);

                    COMUtils.checkRC(result);

                    return count;
                } catch ( Exception e ) {
                    System.out.println("Error : " + e.getMessage());
                }
                return -1;
            }
} 

然后,main中的调用更改为

代码语言:javascript
复制
Imapi2 imapi2Lib = Imapi2.INSTANCE;
        Imapi2.IDiscMaster2 recorderList = new Imapi2.IDiscMaster2();

        System.out.println("Found " + recorderList.getCount() + " Recorders");

IntelliJ显示未调用的方法,因此它看起来不像是create()被调用。不确定这是因为我需要调用它,还是需要调用实现IDispatch而不是IUnknown的函数。1:https://github.com/nosdod/CDInterface

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-11-26 19:02:18

我在类似的问题中回答了这个问题,我最初把它标记为一个副本。但是,考虑到加载这个问题的困难,您的情况非常独特,因此我将尝试给出一个单独的答案。

COM的一般情况是,有一个创建对象的API函数。您已经将其映射为createMsftDiscMaster2()。请注意,您已经在这里分配了一个资源,当您完成该资源时,它需要被释放;API文档应该告诉您如何做到这一点(可能通过从Release()调用IUnknown)。

下一步是映射IDiscMaster2 COM类。我在这里看到了两个映射,所以我搞不懂你想要哪一个。问题顶部的那个是不正确的,但是稍后扩展调度的那个是正确的开始方式,但我不知道你在那之后去了哪里。JNA中应该看上去和内部结构相似类的Dispatch类的其余部分。

在那门课上,你可以看到你将要遵循的样板。注意,它扩展了Unknown,其中遵循相同的样板的偏移量为0、1和2,用于前3个COM函数QueryInterfaceAddRefRelease。对于COM函数GetTypeInfoCountGetTypeInfoGetIDsOfNamesInvoke,使用偏移量3、4、5和6进行分派。

因此,在DiskMaster2的映射中,您将获得偏移量7,您的映射将类似于:

代码语言:javascript
复制
public HRESULT TheFunctionName(FOO foo, BAR bar) {
    return (HRESULT) this._invokeNativeObject(7,
            new Object[] { this.getPointer(), foo, bar },
            HRESULT.class);
}

在这里,您需要定位这个类的实际头文件,以确定函数在Vtbl中的出现顺序。看起来您试图用代码来完成这一任务,但是偏移量2已经在未知中分配了,您可以使用的最低值是7(并按照正确的顺序继续使用8、9、10 对于这个COM接口中的每个函数 --这必须从Vtbl中确定)。

基于此标头,您可以看到按顺序映射的函数,您的偏移量应该是: 7: get__NewEnum、8: get_Item、9: get_Count和10: get_IsSupportedEnvironment。使用这些头函数映射作为开始,并将它们更改为上面的_invokeNativeObject()格式。(它们都返回HRESULT,您只需更改参数列表。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70109741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档