0

我是使用 java 本机接口的新手。我的任务是在

爪哇。我需要在 java 中实现的方法使用 vc++ 中的 dll 方法

方法。我的问题是,在 java 中声明本机方法并调用

本机声明的方法还是我仍然需要将代码从 c++ 重写为 java 使用

杰尼 任何人都可以建议我如何做到这一点,我阅读了文章但没有完全

了解 jni 在做什么。这是我必须在java中实现的方法,

内部调用的方法来自 m_hSecdll,所以我应该如何使用这些方法

java实现这个getauthorization方法

bool HtmlWindow::GetAuthorizationHeader(CString &sName, CString &sValue)
        {          
                //type enum
            SecStatus stat;
                //typedef for long typw
            SecContextHandle hCurrentCtx;
            //typedef for struct
                SecBufferHandle hBuf = NULL; 

            try
            {
                if (!m_hSecdll)
                {
                    m_hSecRtl = AfxLoadLibrary(_T("secdll"));
                }

                if (!m_hSecdll)
                {
                    AfxMessageBox(IDS_ERR_SECDLL);
                    return false;
                }

                //get the function to call SecGetContext
                typedef SecStatus (_stdcall *FN2)(SecContextHandle*);
                FN2 pFN2 = (FN2) ::GetProcAddress(m_hSecRtl, _T("SecGetContext"));
                if (!pFN2)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECGETCONTEXT);
                    return false;
                }

                //call it
                stat = (*pFN2)(&hCurrentCtx);
                if (stat != eSecOk) {
                    AfxMessageBox(IDS_ERR_MPAGES_SERVICE_CONTEXT);
                    return false;
                }

                //get the function to call SecExportContext
                typedef SecStatus (_stdcall *FN3)(SecBufferHandle*, const SecContextHandle, const char*, const uint);
                FN3 pFN3 = (FN3) ::GetProcAddress(m_hSecRtl, _T("SecExportContext"));
                if (!pFN3)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECEXPORTCONTEXT);
                    return false;
                }

                //call it
                stat = (*pFN3)(&hBuf, hCurrentCtx, NULL, 0);
                if (stat != eSecOk) {
                    AfxMessageBox(IDS_ERR_MPAGES_SERVICE_EXPORT);
                    return false;
                }

                //get the function to call SecExportContext
                typedef void* (_stdcall *FN4)(SecBufferHandle);
                FN4 pFN4 = (FN4) ::GetProcAddress(m_hSecRtl, _T("SecGetBufferPtr"));
                if (!pFN4)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECGETBUFFERPTR);
                    return false;
                }

                //call it
                unsigned char * c = (unsigned char*)(*pFN4)(hBuf);

                //get the function to call SecExportContext
                typedef long (_stdcall *FN5)(SecBufferHandle);
                FN5 pFN5 = (FN5) ::GetProcAddress(m_hSecRtl, _T("SecGetBufferLen"));
                if (!pFN5)
                {
                    AfxMessageBox(IDS_ERR_SECRTL_SECGETBUFFERLEN);
                    return false;
                }

                //call it
                int length = (*pFN5)(hBuf);

                int x = 0;
                char * hex = new char[length*2];
                for (int i = 0; i < length; i++)
                {
                    CString sTemp;
                    sTemp.Format("%x",c[i]);
                    if (sTemp.GetLength()==1)
                        sTemp = _TCHAR('0') + sTemp;

                    hex[x++] = sTemp[0];
                    hex[x++] = sTemp[1];
                }

                sName = "Some String";
                sValue = CString(hex,length*2); 
                delete [] hex;

            }
            catch (...)
            {
                AfxMessageBox(IDS_ERR_SECDLL_UNKNOWN);
                return false;
            }

            return true;
    }
4

1 回答 1

0

JNI

使用 JNI,您可以在 C 或 C++ 中实现 Java 方法(类静态成员或对象实例成员)。C 或 C++ 代码使用 JNI 函数将参数从 Java 传输到本地,调用本地函数,然后使用 JNI 函数将返回值从本地传输到 Java。当然,在两种类型系统中具有相同表示的简单类型不需要任何转换。您还可以使用 JNI 函数创建 Java 对象、调用方法、访问字段以及抛出和处理异常。

基本参考:

JNA

使用 JNA,您可以在 Java 中调用 DLL 函数。JNA 在内部使用 JNI,但不是自己编写 C 或 C++,而是编写 Java 代码来描述 JNA 库应如何调用 DLL 函数以及转换参数和返回值。

帮助理解 JNA 的酷工具:

  • JNAerator(与您需要的 DLL 函数和结构的简化 C 头文件一起使用)

获取授权头

这似乎是 C++ 类的成员。如果它不是静态的,并且您需要在 Java 本机方法调用之间保留对它的实例的引用,那么您的问题就会大得多。如果它是静态的(或者可以做成静态的),如果你走 JNI 路线,你可以直接使用它。但是,GetAuthorizationHeader 的实际功能看起来非常简单,因此可以内联重新实现它,或者使用 JNA 路由在 Java 中重新实现。

字符串

每个字符串都有一个字符集和编码(又名代码页)。Java 使用 Unicode UTF-16LE 或 UTF-16BE(取决于平台)。Windows 使用 UTF-16LE。您的代码是使用灵巧的 _T() 宏编写的,并调用灵巧的 Win32 API 函数。Win32有FunctionA函数和FunctionW函数。W 代表 Unicode。您很可能会放弃对不支持 Unicode的Windows版本的支持。如果你在现代 Windows 上调用 A 函数,它必须转换为 Unicode 并再次转换回来,所以你还是调用 W 函数。

Visual C++ 中的字符串文字被写为 Unicode 的 L"string" 并且是类型化的wchar_t并且是 UTF-16LE。在 C++ 中,wchar_t是依赖于平台的字符类型。您的 C++ 版本可能不支持新的 C++ char16_t,因此您可以替换wchar_t.

将 JNI 与字符串一起使用时,您可以调用GetStringCharsNewString函数来从 Win32 API W 函数获取 UTF-16LE 字符串。无需转换;只需确保跟踪代码单元计数和/或字节计数(并为被调用的函数使用正确的计数)。如果您使用的是 C++ 的 STL,那么std::wstring该类可能会有所帮助。

如果您的算法需要特定的编码,那么您必须找出它是什么。然后,您可以使用 Java String 和 Charset 类将编码转换为 Java 字节数组/从 Java 字节数组转换,并将 Java 字节数组转换为/从本机字节数组转换以与您的 DLL 函数一起使用。

可能是您的算法不在乎,但如果两个系统正在交换字符串数据,您可能仍需要使用特定的编码。

于 2013-11-09T21:54:35.690 回答