我是使用java原生界面的新手。我的任务是在
中实现一个vc ++方法的java。我需要在java中实现的方法使用vc ++中的dll方法
方法。我的问题是,在java中声明本机方法并调用
就足够了本机声明的方法或者我仍然需要使用
将代码从c ++重写为javaJNI。任何人都可以建议我如何做到这一点,我读文章,但没有完全
了解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;
}
答案 0 :(得分:0)
使用JNI,您可以在C或C ++中实现Java方法(类静态成员或对象实例成员)。 C或C ++代码使用JNI函数将参数从Java传递到本机,调用本机函数,然后使用JNI函数将返回值从本机传输到Java。当然,在两种类型系统中具有相同表示的简单类型不需要任何转换。您还可以使用JNI函数创建Java对象,调用方法,访问字段以及抛出和处理异常。
基本参考资料:
使用JNA,您可以在Java中调用DLL函数。 JNA在内部使用JNI,但您不是自己编写C或C ++,而是编写Java代码来描述JNA库应如何调用DLL函数并转换参数和返回值。
帮助理解JNA的酷工具:
这似乎是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与字符串一起使用时,可以调用GetStringChars
和NewString
函数以获取与Win32 API W函数之间的UTF-16LE字符串。无需转换;只需确保跟踪code unit计数和/或字节数(并使用适当的函数调用)。如果您使用的是C ++的STL,那么std::wstring
类可能有所帮助。
如果您的算法需要特定的编码,那么您必须找出它是什么。然后,您可以使用Java String和Charset类将编码转换为Java字节数组或从Java字节数组转换编码,并将Java字节数组转换为/从本机字节数组转换为与DLL函数一起使用。
可能你的算法并不关心,但如果两个系统正在交换字符串数据,你可能需要使用特定的编码。