存档

‘c’ 分类的存档

java 调用dll文件总结

2008年4月17日 评论已被关闭

java 调用dll文件时

几个注意点:
1. package的使用
2. javah的使用
3.path路径的设定

 

下面实例介绍java调用dll中的Max函数:

hello.java

package 2hei.net.dll;

public class hello
{
    static
    {
        //System.out.println(System.getProperties().get(“java.library.path”));
        System.loadLibrary(“Hello”);
    } 
    public native static int Max(int a,int b);
   
    public static void main(String[] args)
    {
        int maxnum = 0;
        int aa = 10;
        int bb = 11;
        hello hi= new hello();
        maxnum = hi.Max(aa,bb);
        System.out.println(“max is “+maxnum);        
    }
}

生成.h头文件

createh.bat

cd E:\src\java\2hei\net\dll  

javah hello

会生成一个2hei_net_dll_hello.h的文件

编辑编辑 2hei_net_dll_hello.h  把#include <jni.h> 改成#include “jni.h”

从jdk的目录里面找到jni.h  和 jni_md.h

下面使用VC++生成dll文件。

新建一个dll工程,比如Hello  编辑Hello.cpp

// Hello.cpp : Defines the entry point for the DLL application.
//

#include “stdafx.h”
#include “Hello.h”
#include “2hei_net_dll_hello.h”

JNIEXPORT jint JNICALL 2hei_net_dll_hello_Max
  (JNIEnv *, jclass, jint a, jint b)
{
 if(a>=b)return a;
 else
 return b;
}

编译工程后,在Debug目录中找到Hello.dll文件,放到java的path目录下面。

执行hello.java 即可以得到想要的结果。

 

分类: c, java 标签: ,

构造函数和析构函数

2008年4月8日 评论已被关闭

构造函数的作用是给每个对象的数据成员合适的初始值。构造函数的名字与类的名字相同,没有返回值。一个类可以有多个构造函数,通过不同的形参表进行区分。
创建一个类的对象时,编译器自动调用构造函数。
构造函数不能声明为const。当创建的类的对象为const时,调用普通的构造函数即可。const Item A = Item();
构造函数可以包含一个初始化列表。初始化列表以 “:”开始,以“,”分隔数据成员,每个数据成员后面是放在括号里的初始化式。(初始化式只在构造函数的定义中,不在声明中出现。)
Sales_item::sales_item(const string book):isbn(book),units_sold()0 {}
类通过默认构造函数初始化没有被显示初始化的成员变量。没有默认构造函数的类类型以及const或饮用类型的成员必须在构造函数初始化列表中进行初始化。
构造函数初始化列表仅指定用于初始化成员的值,并不指定初始化的顺序。成员被初始化的顺序就是声明成员的顺序。建议按照成员声明的顺序编写初始化列表。
如果类包含内置或复合类型(如指针、数组),应该定义自己的构造函数来初始化这些成员。
当构造函数声明为explicit时,可以防止在需要隐式转换的上下文中使用构造函数。
每个派生类构造函数除了初始化自己的数据成员以外,还要初始化基类成员,但是只能初始化直接基类的成员。直接基类就是在派生类列表中指定的类。
派生类执行构造函数时,先执行基类的构造函数,然后初始化派生类中的成员。
基类可以被包含在派生类的初始化列表中,从而被初始化。

析构函数用以完成资源释放。
只有删除指向动态分配对象的指针或实际对象(不是对象引用)超出作用域时,才会运行析构函数。
编译器总会合成一个析构函数。合成的析构函数按照对象创建时的逆序撤销每个非static成员。不删除指针成员所指的对象。
析构函数没有返回值,没有形参。

分类: c 标签:

C++中的虚函数(学习)

2008年4月2日 评论已被关闭

虚函数实现C++中的多态(polymorphism)。只有指定为虚函数的成员才能进行动态绑定。必须通过基类的引用或指针对虚函数进行调用。
通过引用或指针调用虚函数时,编译器将生成代码,运行时确定调用哪个函数。被调用的函数时与动态类型相对应的。
虚函数编译处理的方式:
VTABLE机制。编译器发现一个类中有虚函数时,会为其创建一个虚函数表,即VTABLE。VTABLE实际上是一个函数指针的数组,每个函数占用这个数组的一个slot。一个类只有一个VTABLE。派生类有自己的VTABLE,与基类有相同的函数排列顺序。创建类实例,调用构造函数时,编译器会在每个实例的内存区中增加一个VPTR字段,该字段指向VTABLE。
虚函数的语法:virtual function();
基类中声明的虚函数在派生类中也是虚函数。

基类的析构函数必须是虚函数。
class A
{
  ~A();
}

class B
{
  ~B();
}

void foo
{
  A *a = new B;
  delete a;
}

上面的例子,delete a时,只有A::~A()被调用,B::~B()没有被调用。将A的析构函数改为virtual ~A(),上面例子中的B::~B()才被调用。
基类private 的虚函数,派生类可以访问。
一个类的虚函数在它自己的构造函数和虚函数中调用时,就变成普通函数了。

纯虚函数: virtual function() = 0;
一个函数声明为纯虚函数后,其所在的类为抽象类,不能被实例化。

分类: c 标签:

引用 C++

2008年3月27日 评论已被关闭

一直对C++中的引用没有太深刻的认识,这几天趁着工作不忙,认真地学一习了一番,在这里总结一下。

引用(reference):某一变量的别名,对引用的操作与对对象的操作一样。

引用的声明方法: 类型标示符 &引用名 = 目标变量名

声明引用时,必须同时对其进行初始化。

一旦引用被初始化指向一个对象,不能改变为另一个对象的引用。(这一点是与指针的最大区别)

引用不能为NULL。

引用最大的作用是用作函数的参数。当引用被函数改变时,相应的变量被改变。如果传递的数据块比较大,使用引用或指针,可以避免将整块数据全部压栈。

常引用

const 类型标示符 & 引用名 = 目标变量名

不能通过引用,修改目标变量值。引用型参数应该在能被定义为const的情况下尽量定义为const。

 

分类: c 标签:

在C++中使用delete、free

2008年3月6日 评论已被关闭

今天看了一篇文章,才知道自己对delete和free的理解不对。

从前以为指针使用delete或free释放之后就万事大吉了,但事实上用delete和free释放指针内存后,指针并不会被置为空。如果在后面的程序通过判断指针是否为空来进行不同的操作,很可能导致错误,所以,今后在用delete和free释放指针内存后,一定要把指针置为空。

既然谈到了delete和free,就要说说new/delete和malloc/free。

delete和free是C++的运算符,malloc和free是C++/C语言的标准库函数,它们都是用来动态的申请和释放内存。new和delete用于对象的申请和释放。new可以完成动态内存分配和初始化工作(构造过程),delete完成清理与释放内存的工作(析构过程)。malloc和free用于类内部数据类型(无需构造和析构)内存的申请和释放。

用new创建数组,只能用对象的无参数构造函数:

Obj *objects = new Obj[100];

在用delete释放对象数组是,不要丢了[]:

delete []objects;

如果用delete objects;相当于delete objects[0],漏掉了另外99个对象。

 

分类: c 标签: