使用jni在java中实现vc ++方法

时间:2013-11-08 21:31:36

标签: java windows visual-c++ java-native-interface native-code

我是使用java原生界面的新手。我的任务是在

中实现一个vc ++方法

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

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

就足够了

本机声明的方法或者我仍然需要使用

将代码从c ++重写为java

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

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

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

中使用这些方法

java实现这种认证方法

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;
    }

1 个答案:

答案 0 :(得分: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(与简化的C头一起用于您需要的DLL函数和结构)

GetAuthorizationHeader

这似乎是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字符串。无需转换;只需确保跟踪code unit计数和/或字节数(并使用适当的函数调用)。如果您使用的是C ++的STL,那么std::wstring类可能有所帮助。

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

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