我正在尝试创建一个c ++类并将其对象保存到一个数组中,并使用JNI从java引用那些c ++对象,因为JNI没有提供任何机制来将任何非原始类型的对象保存到java中。
我已经实现了下面提到的代码,但是输出显示我好像创建了多个对象,并且我在第二次调用时也收到堆错误以创建新的本机对象。
任何人都可以看一下吗?
感谢
代码:
Java类(加载库dll的函数已在LibObj中定义):
package org.jnp.pkg004;
import org.jnp.libloader.LibObj;
public class PureCppObjFactory extends LibObj {
private long cppobjlstsz;
public PureCppObjFactory() {
super();
cppobjlstsz=0;
}
public native void newCppObj();
public native void PrintCppObjDetails(long cppobjlstindex);
}
C ++库代码:
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "org_jnp_pkg004_PureCppObjFactory.h"
class NativeObjClass
{
private:
int num_ran;
int obj_num;
public:
static int obj_cnt;
NativeObjClass()
{
obj_cnt++;
obj_num=obj_cnt;
num_ran=rand();
cout<<"Native Object number "<<setfill('0')<<setw(5)<<obj_cnt<<" Random number:"<<num_ran<<endl;
}
int get_obj_num()
{
return obj_num;
}
int get_num_ran()
{
return num_ran;
}
};
int NativeObjClass::obj_cnt=0;
NativeObjClass *nobj_lst;
long nobj_lst_size=0;
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_newCppObj
(JNIEnv *env, jobject obj)
{
jclass thisCls = env->GetObjectClass(obj);
jfieldID fid=env->GetFieldID(thisCls,"cppobjlstsz","J");
NativeObjClass nobj;
jlong java_lst_sz=env->GetLongField(obj,fid);
NativeObjClass *temp_nobj_lst;
temp_nobj_lst=new NativeObjClass[nobj_lst_size];
if(nobj_lst_size>0)
{
memmove(temp_nobj_lst,nobj_lst,nobj_lst_size);
delete nobj_lst;
}
nobj_lst_size++;
nobj_lst=new NativeObjClass[nobj_lst_size];
if(nobj_lst_size>1)
{
memmove(nobj_lst,temp_nobj_lst,nobj_lst_size);
delete temp_nobj_lst;
}
nobj_lst[nobj_lst_size]=nobj;
java_lst_sz++;
env->SetLongField(obj,fid,java_lst_sz);
}
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_PrintCppObjDetails
(JNIEnv *env, jobject obj, jlong indx)
{
NativeObjClass nobj=nobj_lst[indx];
cout<<"Retrieved Native Object number "<<setfill('0')<<setw(5)<<nobj.get_obj_num()<<" Random number:"<<nobj.get_num_ran()<<endl;
}
包含main的类:
package test.jnp.pkg004;
import org.jnp.pkg004.PureCppObjFactory;
public class PureCppObjFactoryTest {
public static void main(String[] args) {
PureCppObjFactory pcf=new PureCppObjFactory();
pcf.newCppObj();
pcf.PrintCppObjDetails(0);
pcf.newCppObj();
//pcf.newCppObj();
}
}
输出:
Native Object number 00001 Random number:41
Native Object number 00002 Random number:18467
Retrieved Native Object number 00002 Random number:18467
Native Object number 00003 Random number:6334
Native Object number 00004 Random number:26500
此代码执行后也会弹出堆错误
答案 0 :(得分:3)
好的,这是乍看之下的问题清单:
using namespace std;
表格不好static int obj_cnt;
不是线程安全NativeObjClass *nobj_lst;
应该是静态成员NativeObjClass *nobj_lst;
应该是std :: vector long nobj_lst_size=0;
应该是静态成员long nobj_lst_size=0;
应为size_t
NativeObjClass nobj;
创建了一个对象 - 它不仅仅是一个参考nobj_lst=(NativeObjClass*)calloc(nobj_lst_size,sizeof(NativeObjClass));
完全错了。如果您必须使用手动管理的阵列,请使用new[]
,但std::vector
仍然会更好nobj_lst[nobj_lst_size-1]=nobj
复制您创建的对象NativeObjClass nobj=nobj_lst[indx];
制作数组对象的无意义副本请考虑这种方法。请注意,以下代码尚未经过测试或编译,只是为了显示这个想法。
public class CppObject {
private long handle;
public CppObject() {
handle = createNativeObject();
}
public void cleanup() {
deleteNativeObject(handle);
handle = 0;
}
private static native long createNativeObject();
private static native void deleteNativeObject(long handle);
private static native void printObjectDetails(long handle);
public void PrintObjDetails() {
printObjectDetails(handle);
}
}
JNIEXPORT jlong JNICALL whatever_createNativeObject(JNIEnv *env, jobject obj) {
return reinterpret_cast<jlong>(new CppObject());
}
JNIEXPORT void JNICALL whatever_deleteNativeObject(JNIEnv *env, jobject obj, jlong handle) {
delete reinterpret_cast<CppObject *>(handle);
}
JNIEXPORT void JNICALL printObjectDetails(JNIEnv *env, jobject obj, jlong handle) {
reinterpret_cast<CppObject *>(handle)->printDetails();
}
java long是64位,因此上述代码在32位和64位平台上都可以正常工作。
答案 1 :(得分:0)
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "org_jnp_pkg004_PureCppObjFactory.h"
class NativeObjClass
{
private:
int num_ran;
int obj_num;
public:
static int obj_cnt;
NativeObjClass()
{
obj_cnt++;
obj_num=obj_cnt;
num_ran=rand();
cout<<"Native Object number "<<setfill('0')<<setw(5)<<obj_cnt<<" Random number:"<<num_ran<<endl;
}
int get_obj_num()
{
return obj_num;
}
int get_num_ran()
{
return num_ran;
}
};
int NativeObjClass::obj_cnt=0;
NativeObjClass *nobj_lst;
long nobj_lst_size=0;
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_newCppObj
(JNIEnv *env, jobject obj)
{
jclass thisCls = env->GetObjectClass(obj);
jfieldID fid=env->GetFieldID(thisCls,"cppobjlstsz","J");
NativeObjClass nobj;
jlong java_lst_sz=env->GetLongField(obj,fid);
if(nobj_lst_size==0)
{
nobj_lst_size++;
nobj_lst=(NativeObjClass*)calloc(nobj_lst_size,sizeof(NativeObjClass));
nobj_lst[nobj_lst_size-1]=nobj;
}
else
{
nobj_lst_size++;
nobj_lst=(NativeObjClass*)realloc(nobj_lst,nobj_lst_size*sizeof(NativeObjClass));
nobj_lst[nobj_lst_size-1]=nobj;
}
java_lst_sz++;
env->SetLongField(obj,fid,java_lst_sz);
}
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_printCppObjDetails
(JNIEnv *env, jobject obj, jlong indx)
{
NativeObjClass nobj=nobj_lst[indx];
cout<<"Retrieved Native Object number "<<setfill('0')<<setw(5)<<nobj.get_obj_num()<<" Random number:"<<nobj.get_num_ran()<<endl;
}