由于要做短信,买了一台GSM Modem,提一个C++的DLL开发接口,DLL文件名:sms.dll,这个dll用VC编译应用程序测试完全正常。
由于需要在Java里面调用,则要用VC按jni规范重新封装sms.dll成dll才能被java调用。在用VC重新封装sms.dll的dll中可以加载sms.dll,但用GetProcAddress取不到sms.dll函数中的入口地址,返回错误代码(126:找不到指定模块),用depends查看函数书写正确,就是找不到。问题要点:1.sms.dll用VC程序测试调用正常;
2.sms.dll再封装成dll,在新dll中就找到调用函数的入口地址。真是奇了怪了,请高人帮忙。我的QQ:999975
由于需要在Java里面调用,则要用VC按jni规范重新封装sms.dll成dll才能被java调用。在用VC重新封装sms.dll的dll中可以加载sms.dll,但用GetProcAddress取不到sms.dll函数中的入口地址,返回错误代码(126:找不到指定模块),用depends查看函数书写正确,就是找不到。问题要点:1.sms.dll用VC程序测试调用正常;
2.sms.dll再封装成dll,在新dll中就找到调用函数的入口地址。真是奇了怪了,请高人帮忙。我的QQ:999975
HINSTANCE hinstDLL=NULL;JNIEXPORT jint JNICALL Java_com_rhinofield_common_GsmModemInterface_sms_1LoadSmsDll
(JNIEnv *env, jclass, jstring cls)
{
if(hinstDLL==NULL)
{
//加载DLL
hinstDLL=LoadLibrary(_T("sms.dll"));
if(hinstDLL==NULL)
return 0;
}
return 1;
}JNIEXPORT jint JNICALL Java_com_rhinofield_common_GsmModemInterface_sms_1UnloadSmsDll
(JNIEnv *env, jclass cls)
{
if(hinstDLL!=NULL)
{
//卸载DLL
FreeLibrary(hinstDLL);
return 1;
}
return 0;
}JNIEXPORT jstring JNICALL Java_com_rhinofield_common_GsmModemInterface_Sms_1Connection
(JNIEnv *env, jclass cls, jstring copyRight, jint com_Port, jint com_BaudRate)
{
const char *cr=env->GetStringUTFChars(copyRight, NULL);
//CString csCopyRight="";
//csCopyRight.Format(_T("%s"),cr);
//env->ReleaseStringUTFChars(copyRight, cr); //char *buffer2=(char *)(LPCTSTR)csCopyRight;
//jstring result = env->NewStringUTF(buffer2);
//env->ReleaseStringUTFChars(copyRight, cr);
//return result; char *buffer2=NULL;
//CString mobile_Type[256];
if(hinstDLL==NULL)
buffer2="1:hinstDLL=NULL";
else
{
//typedef int(_stdcall *Sms_Connection)(int Com_Port,int Com_BaudRate,CString *Mobile_Type);
//Sms_Connection Proc=(Sms_Connection)GetProcAddress(hinstDLL,"Sms_Connection");
typedef int(_stdcall *Sms_NewFlag)();
Sms_NewFlag Proc = (Sms_NewFlag)GetProcAddress(hinstDLL,"Sms_NewFlag");
************************在这个地方出错,Proc=NULL*********************
if(Proc==NULL)
{
DWORD abc=GetLastError();
buffer2=new char[10];
_ultoa( abc, buffer2, 10 );
//buffer2="2:Proc=NULL";
}
else
{
buffer2="3:Proc!=NULL";
/*
int rtnValue = Proc(com_Port,com_BaudRate,mobile_Type);
if(rtnValue==0)
buffer2="3:rtnValue=0";
else
{
CString temp="1;"+*mobile_Type;
buffer2=(char *)(LPCTSTR)temp;
}
*/
}
}
jstring result = env->NewStringUTF(buffer2); /*
CString temp="";
temp.Format(_T("%d"),rtnValue);
if(rtnValue!=0)
{
temp=temp+";"+*mobile_Type;
}
buffer=(char *)temp.GetBuffer();
jstring result = stoJstring(env,buffer);
*/
//free(buffer);
return result;
}
LoadLibrary最初值是1,GetProAddress时的值是119537664
汗一个,是不是hinstDLL的状态没有保存?
中间肯定没有FreeLibrary
java调用代码如下: int value=sms_LoadSmsDll("");
System.out.println("DLLHandle="+value);
if(value!=0)
{
String rtnValue=Sms_Connection("Hello,world!",5,9600);
if(rtnValue.length()<=1)
{
System.out.println("Connection failed!");
}
else
{
System.out.println("Connection success!Mobile_Type="+rtnValue.substring(0));
}
}
else
{
System.out.println("Open sms.dll failed!");
}
value=sms_UnloadSmsDll();
if(value==1)
System.out.println("close sms.dll success!");
else
System.out.println("close sms.dll failed!");
return 0;
是126,意思是找不到模块。我用depends看过,函数名称书写正确,况且在VC应用程序里面调用sms.dll是可以的,在DLL里面就出问题
这样是可以的,谢谢兄弟!但如果不用全程变量,哪么LoadLibrary只能放在函数里面,则每调用一次函数就要加载DLL,这样效率会很低,兄弟有没有其他解决办法?
你可以试试在sms.dll的DllMain中的DLL_PROCESS_DETACH分支中加个断点,当执行到断点时,根据调用堆栈来看是哪里调用的FreeLibrary。
每调用一次函数就要加载DLL?这样啊?哪有这么囧的?不妨把所有要调用的函数设为全局成员变量,LoadLibrary后都GetProcAddress掉。建议可以弄个结构体数组,数组元素由函数名和函数地址2个元素组成,这样很方便
声明入口函数的时候加上Extern C