Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,长修远,我们不能没有钱

GCC Mingw编译JNI dll要点

本来想做一个win32平台下, 由于vc没有psapi.dll的库. 所以选择了mingw包和gcc编译器.

java部分
这里主要是申明接口. javah工具会根据你声明的接口自动生成对于的.h头文件

//SystemInfo.java
package com.khan.system;

public abstract class SystemInfo
{
    // public: ................................................................
   
    /**
    * A simple class to represent data snapshots taken by {@link #makeCPUUsageSnapshot}.
    */
  public static final class CPUUsageSnapshot {
    public final long m_time, m_CPUTime;
   
      // constructor is private to ensure that makeCPUUsageSnapshot()
      // is used as the factory method for this class:
    private CPUUsageSnapshot (final long time, final long CPUTime) {
      m_time = time;
      m_CPUTime = CPUTime;
    }
   
  } // end of nested class



    // Custom exception class for throwing
  public static final class NegativeCPUTime extends Exception {}


    /**
    * Minimum time difference [in milliseconds] enforced for the inputs into
    * {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.
    * The motivation for this restriction is the fact that <CODE>System.currentTimeMillis()</CODE>
    * on some systems has a low resolution (e.g., 10ms on win32). The current value
    * is 100 ms.
    */
  public static final int MIN_ELAPSED_TIME = 100;


    /**
    * Creates a CPU usage data snapshot by associating CPU time used with system
    * time. The resulting data can be fed into
    * {@link #getProcessCPUUsage(SystemInfo.CPUUsageSnapshot,SystemInfo.CPUUsageSnapshot)}.
    */
  public static CPUUsageSnapshot makeCPUUsageSnapshot() throws SystemInfo.NegativeCPUTime {
    long prCPUTime = getProcessCPUTime ();
    if (prCPUTime<0)
      throw new NegativeCPUTime();
    return new CPUUsageSnapshot (System.currentTimeMillis (), getProcessCPUTime ());
  }

    /**
    * Computes CPU usage (fraction of 1.0) between <CODE>start.m_CPUTime</CODE> and
    * <CODE>end.m_CPUTime</CODE> time points [1.0 corresponds to 100% utilization of
    * all processors].
    *
    * @throws IllegalArgumentException if start and end time points are less than
    * {@link #MIN_ELAPSED_TIME} ms apart.
    * @throws IllegalArgumentException if either argument is null;
    */
  public static double getProcessCPUUsage (final CPUUsageSnapshot start, final CPUUsageSnapshot end) {
    if (start == null)
      throw new IllegalArgumentException ("null input: start");
    if (end == null)
      throw new IllegalArgumentException ("null input: end");
    if (end.m_time < start.m_time + MIN_ELAPSED_TIME)
      throw new IllegalArgumentException ("end time must be at least " + MIN_ELAPSED_TIME + " ms later than start time");
       
    return ((double)(end.m_CPUTime - start.m_CPUTime)) / (end.m_time - start.m_time);
  }

    /**
    * Returns the PID of the current process. The result is useful when you need
    * to integrate a Java app with external tools.
    */
  public static native int getProcessID ();

    /**
    * Returns the number of processors on machine
    */
  public static native int getCPUs ();


    /**
    * Returns CPU (kernel + user) time used by the current process [in milliseconds].
    * The returned value is adjusted for the number of processors in the system.
    */
  public static native long getProcessCPUTime ();


    /**
    * Returns CPU (kernel + user) time used by the current process [in perecents].
    * The returned value is either CPU percentage, or zero if this is not supported by OS.
    * Currently it is supported by Solaris8, and not supported by Windows XP
    */
  public static native double getProcessCPUPercentage();

    /**
    * Returns maximum memory available in the system.
    */
  public static native long getMaxMem ();

    /**
    * Returns current free memory in the system.
    */
  public static native long getFreeMem ();

    /**
    * Returns system name info like "uname" command output
    */
  public static native String getSysInfo ();


    /**
    * Returns CPU usage (fraction of 1.0) so far by the current process. This is a total
    * for all processors since the process creation time.
    */
  public static native double getProcessCPUUsage ();

    /**
    * Returns current space allocated for the process, in Kbytes. Those pages may or may not be in memory.
    */
  public static native long getMemoryUsage();


    /**
    * Returns current process space being resident in memory, in Kbytes.
    */
  public static native long getMemoryResident();


    /**
    * Sets the system native process PID for which all measurements will be done.
    * If this method is not called then the current JVM pid will act as a default.
    * Returns the native-dependent error code, or 0 in case of success.
    */
  public static native int setPid(int pid);

    /**
    * Closes native-dependent process handle, if necessary.
    */
  public static native int detachProcess();

    // protected: .............................................................

    // package: ...............................................................

    // private: ...............................................................


  private SystemInfo() {} // prevent subclassing

  private static final String SILIB = "SystemInfo";

  static {
    // loading a native lib in a static initializer ensures that it is
    // available done before any method in this class is called:
    try {
      System.loadLibrary (SILIB);
    }catch (UnsatisfiedLinkError e){
      System.out.println("native lib '" + SILIB
                         + "' not found in 'java.library.path': "
                         + System.getProperty ("java.library.path"));
    }catch (Exception e){
      System.out.println(e.getMessage());
    }
  }

} // end of class


//AppMain.java 测试文件
package com.khan.system;

public class AppMain {
    /**
     * Default constructor
     */
    public AppMain() {
        // TODO: Add constructor code here
    }


    public static void main(String[] args) {
      try {
        Thread.sleep(1000);
        System.out.println("getMaxMem:" + SystemInfo.getMaxMem());
        System.out.println("getCPUs:" + SystemInfo.getCPUs());
        System.out.println("getSysInfo:" + SystemInfo.getSysInfo());
      }catch (Exception e){
        System.out.println(e.getMessage());
      }
    }

}

java部分工程文件. 等同与makefile
ant build.xml

<project name="IpNet" default="build" basedir=".">
  <description>
    simple example build file
  </description>
  <!-- set global properties for this build -->
  <property name="name" value="IpNet"/>
  <property name="src" location="src"/>
  <property name="build" location="build"/>
  <property name="dist"  location="dist"/>
  <property name="web"  location="web/WEB-INF/lib"/>

  <path id="master-classpath">
    <fileset dir="./lib">
      <include name="*.jar"/>
    </fileset>
  </path>

  <target name="init">
    <tstamp/>
    <mkdir dir="${build}"/>
    <mkdir dir="${dist}"/>
  </target>

  <target name="build" depends="init" description="compile the source " >
    <javac srcdir="${src}" destdir="${build}">
      <compilerarg value="-Xlint:unchecked"/>
      <compilerarg value="-deprecation"/>
      <classpath refid="master-classpath"/>
    </javac>
 
    <copy todir="${build}" preservelastmodified="true">
      <fileset dir="${src}">
        <include name="*.class"/>
      </fileset>
    </copy>
     
    <jar jarfile="${dist}/${name}.jar" compress="true">
      <fileset dir="${build}">
        <include name="**"/>
      </fileset>
    </jar>

    <copy todir="${web}" >
      <fileset dir="${dist}">
        <include name="${name}.jar"/>
      </fileset>
    </copy>
  </target>
 
  <target name="clean" description="clean up" >
    <delete dir="${build}"/>
    <delete dir="${dist}"/>
    <delete file="${web}/${name}.jar"/>
  </target>
</project>

在工程目录下ant 编译工程
build目录为本工程目标二进制文件目录. 编译后的class在此目录下
然后到build目录下
javah javah -jni com.khan.system.SystemInfo //注意, 一定要使用包全路径. 如果不是default包的话.
会在此目录下生成3个.h文件
com_khan_system_SystemInfo.h
com_khan_system_SystemInfo_CPUUsageSnapshot.h
com_khan_system_SystemInfo_NegativeCPUTime.h


java这边的准备工作完成

接下来处理c部分
新建一个c工程. 我用gcc的. 所以这些部分我手工完成的
将刚刚的.h文件实现

/* ------------------------------------------------------------------------- */
/*
 * An implementation of JNI methods in com.vladium.utils.SystemInformation
 * class. The author compiled it using Microsoft Visual C++ and GCC for Win32 but the code
 * should be easy to use with any compiler for win32 platform.
 *
 * For simplicity, this implementaion assumes JNI 1.2+ and omits error handling.
 *
 * Enhanced by Peter V. Mikhalenko (C) 2004, Deutsche Bank [peter@mikhalenko.com]
 * Original source (C) 2002, Vladimir Roubtsov [vlad@trilogy.com]
 */
/* ------------------------------------------------------------------------- */


#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <winbase.h>
#include <psapi.h>
#include <string.h>


#include "include/com_khan_system_SystemInfo.h"



static jint s_PID;
static HANDLE s_currentProcess;
static int alreadyDetached;
static int s_numberOfProcessors;
static SYSTEM_INFO systemInfo;
static WORD processorArchitecture;
static DWORD pageSize;
static DWORD processorType;
static WORD processorLevel;
static WORD processorRevision;

#define INFO_BUFFER_SIZE 32768
#define BUFSIZE 2048

//BOOL flll = TRUE;
/* ------------------------------------------------------------------------- */

/*
 * A helper function for converting FILETIME to a LONGLONG [safe from memory
 * alignment point of view].
 */
static LONGLONG fileTimeToInt64 (const FILETIME * time)
{
    ULARGE_INTEGER _time;

    _time.LowPart = time->dwLowDateTime;
    _time.HighPart = time->dwHighDateTime;

    return _time.QuadPart;
}
/* ......................................................................... */

/*
 * This method was added in JNI 1.2. It is executed once before any other
 * methods are called and is ostensibly for negotiating JNI spec versions, but
 * can also be conveniently used for initializing variables that will not
 * change throughout the lifetime of this process.
 */
JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void * reserved)
{
  s_PID = _getpid ();
  s_currentProcess = GetCurrentProcess ();
  //externalCPUmon = 0;
  alreadyDetached = 0;

  GetSystemInfo (&systemInfo);
  s_numberOfProcessors = systemInfo.dwNumberOfProcessors;
  processorArchitecture = systemInfo.wProcessorArchitecture;
  pageSize = systemInfo.dwPageSize;
  processorType = systemInfo.dwProcessorType;
  processorLevel = systemInfo.wProcessorLevel;
  processorRevision = systemInfo.wProcessorRevision;
  printf("SystemInfo.dll is Loaded");
  return JNI_VERSION_1_2;
}
/* ......................................................................... */

JNIEXPORT void JNICALL
JNI_OnUnload (JavaVM * vm, void * reserved)
{
  if (!alreadyDetached && s_currentProcess!=NULL) {
    CloseHandle(s_currentProcess);
    printf("[JNI Unload] Detached from native process.");
    fflush(stdout);
  }
  printf("SystemInfo.dll is UnLoaded");
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getCPUs
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_khan_system_SystemInfo_getCPUs(JNIEnv * env, jclass cls)
{
    return (jint)s_numberOfProcessors;
}
/* ......................................................................... */



/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getProcessID
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_getProcessID(JNIEnv * env, jclass cls)
{
    return s_PID;
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    setPid
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_setPid(JNIEnv * env, jclass cls, jint pid)
{
    DWORD errCode;
    LPVOID lpMsgBuf;
    s_PID = pid;
    s_currentProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
    if (s_currentProcess==NULL) {
     errCode = GetLastError();
     FormatMessage(
              FORMAT_MESSAGE_ALLOCATE_BUFFER |
              FORMAT_MESSAGE_FROM_SYSTEM,
              NULL,
              errCode,
              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
              (LPTSTR) &lpMsgBuf,
              0, NULL );
   
     printf("[CPUmon] Could not attach to native process. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
     fflush(stdout);
     LocalFree(lpMsgBuf);
     return errCode;
    }
    printf("[CPUmon] Attached to native process.");
    fflush(stdout);
    return 0;
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    detachProcess
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_com_khan_system_SystemInfo_detachProcess(JNIEnv * env, jclass cls)
{
    if (!alreadyDetached && s_currentProcess!=NULL) {
     CloseHandle(s_currentProcess);
     alreadyDetached = 1;
     printf("[CPUmon] Detached from native process.");
     fflush(stdout);
    }
    return 0;
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getProcessCPUTime
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUTime (JNIEnv * env, jclass cls)
{
    FILETIME creationTime, exitTime, kernelTime, userTime;
    DWORD errCode;
    LPVOID lpMsgBuf;
 
    BOOL resultSuccessful = GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
    if (!resultSuccessful) {
     errCode = GetLastError();
     FormatMessage(
              FORMAT_MESSAGE_ALLOCATE_BUFFER |
              FORMAT_MESSAGE_FROM_SYSTEM,
              NULL,
              errCode,
              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
              (LPTSTR) &lpMsgBuf,
              0, NULL );
   
     printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);

     fflush(stdout);
     LocalFree(lpMsgBuf);
     return -1;
    }

    return (jlong) ((fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime)) /
        (s_numberOfProcessors * 10000));
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getMaxMem
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMaxMem(JNIEnv * env, jclass cls)
{
 MEMORYSTATUS stat;
 GlobalMemoryStatus (&stat);
        return (jlong)(stat.dwTotalPhys/1024);
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getFreeMem
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getFreeMem (JNIEnv * env, jclass cls)
{
        MEMORYSTATUS stat;
 GlobalMemoryStatus (&stat);
        return (jlong)(stat.dwAvailPhys/1024);
}
/* ......................................................................... */


/* define min elapsed time (in units of 10E-7 sec): */
#define MIN_ELAPSED_TIME (10000)

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getProcessCPUUsage
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUUsage(JNIEnv * env, jclass cls)
{
    FILETIME creationTime, exitTime, kernelTime, userTime, nowTime;
    LONGLONG elapsedTime;
    DWORD errCode;
    LPVOID lpMsgBuf;
 
    BOOL resultSuccessful = GetProcessTimes (s_currentProcess, & creationTime, & exitTime, & kernelTime, & userTime);
    if (!resultSuccessful) {
     errCode = GetLastError();
     FormatMessage(
              FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
              NULL,
              errCode,
              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
              (LPTSTR) &lpMsgBuf,
              0, NULL );
   
     printf("[CPUmon] An error occured while trying to get CPU time. Error code: %ld Error description: %s", errCode, (char *)lpMsgBuf);
     fflush(stdout);
     LocalFree(lpMsgBuf);
     return -1.0;
    }
    GetSystemTimeAsFileTime (& nowTime);

    /*
        NOTE: win32 system time is not very precise [~10ms resolution], use
        sufficiently long sampling intervals if you make use of this method.
    */
 
    elapsedTime = fileTimeToInt64 (& nowTime) - fileTimeToInt64 (& creationTime);
 
    if (elapsedTime < MIN_ELAPSED_TIME)
        return 0.0;
    else
        return ((jdouble) (fileTimeToInt64 (& kernelTime) + fileTimeToInt64 (& userTime))) /
            (s_numberOfProcessors * elapsedTime);
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getProcessCPUPercentage
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL
Java_com_khan_system_SystemInfo_getProcessCPUPercentage (JNIEnv * env, jclass cls)
{
 // Not implemented on Windows
        return (jdouble)(-1.0);
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getMemoryUsage
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMemoryUsage (JNIEnv * env, jclass cls)
{
    PROCESS_MEMORY_COUNTERS pmc;
 
    if ( GetProcessMemoryInfo( s_currentProcess, &pmc, sizeof(pmc)) )
    {
 return (jlong)(pmc.PagefileUsage/1024);
    } else {
 return (jlong)(0);
    }
}
/* ......................................................................... */

/*
 * Class:     com_vladium_utils_SystemInformation
 * Method: getMemoryResident * Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_com_khan_system_SystemInfo_getMemoryResident(JNIEnv * env, jclass cls)
{
    PROCESS_MEMORY_COUNTERS pmc;
 
    if ( GetProcessMemoryInfo( s_currentProcess, &pmc, sizeof(pmc)) )
    {
        return (jlong)(pmc.WorkingSetSize/1024);
    } else {
         return (jlong)(0);
    }
}


/*
 * Class:     com_vladium_utils_SystemInformation
 * Method:    getSysInfo
 * Signature: ()S
 */
JNIEXPORT jstring JNICALL
Java_com_khan_system_SystemInfo_getSysInfo(JNIEnv * env, jclass cls)
{
  char buf[2048];
  char buf2[512];
  jstring retval;
  OSVERSIONINFOEX osvi;
  BOOL bOsVersionInfoEx;
  TCHAR infoBuf[INFO_BUFFER_SIZE];

  DWORD bufCharCount = INFO_BUFFER_SIZE;
  *buf = 0; //c语言. 变量定义所有代码在前
  *buf2 = 0;
  ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
  {
    osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
    if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) {
      // Return empty string in case of problems
      goto next_label;
    }
  }
   
  switch (osvi.dwPlatformId)
  {
    // Test for the Windows NT product family.
    case VER_PLATFORM_WIN32_NT:

      // Test for the specific product.
      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
        strcat(buf,"WinServer2003, ");

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
        strcat(buf,"WinXP ");

      if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
        strcat(buf,"Win2K ");

      if ( osvi.dwMajorVersion <= 4 )
        strcat(buf,"WinNT ");

      // Display service pack (if any) and build number.

      if( osvi.dwMajorVersion == 4 && lstrcmpi( osvi.szCSDVersion, "Service Pack 6" ) == 0 )
      {
        HKEY hKey;
        LONG lRet;

        // Test for SP6 versus SP6a.
        lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWAREMicrosoftWindows NTCurrentVersionHotfixQ246009", 0, KEY_QUERY_VALUE, &hKey );
        if( lRet == ERROR_SUCCESS ) {
          sprintf(buf2, "SP 6a (Build %d), ", (int)(osvi.dwBuildNumber & 0xFFFF) );       
          strcat(buf,buf2);
        }
        else // Windows NT 4.0 prior to SP6a
        {
          sprintf(buf2, "%s (Build %d), ",
          osvi.szCSDVersion,
          (int)(osvi.dwBuildNumber & 0xFFFF));
          strcat(buf,buf2);
        }

        RegCloseKey( hKey );
      }
      else // not Windows NT 4.0
      {
        sprintf(buf2, "%s (Build %d), ", osvi.szCSDVersion, (int)(osvi.dwBuildNumber & 0xFFFF));
        strcat(buf,buf2);
      }
      break;

      // Test for the Windows Me/98/95.
    case VER_PLATFORM_WIN32_WINDOWS:
      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
      {
        strcat(buf,"Win95 ");
        if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
          strcat(buf,"OSR2 " );
      }

      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
      {
        strcat(buf,"Win98 ");
        if ( osvi.szCSDVersion[1] == 'A' )
          strcat(buf,"SE " );
      }

      if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
      {
        strcat(buf,"WinME ");
      }
      break;

    case VER_PLATFORM_WIN32s:
      strcat(buf,"Win32s ");
      break;
  }
   
next_label:

  strcat(buf,"on ");
  // Get and display the name of the computer.
  bufCharCount = INFO_BUFFER_SIZE;
  if( !GetComputerName( infoBuf, &bufCharCount ) )
    goto next_label_2;
  strcat(buf, infoBuf );
 
next_label_2:
  strcat(buf," (");
  if (!(osvi.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)) {
    // Win95 does not keep CPU info in registry
    LONG lRet;
    HKEY hKey;
    char szOrigCPUType[BUFSIZE];
    int i=0;
    DWORD dwBufLen=BUFSIZE;
    lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWAREDESCRIPTIONSystemCentralProcessor", 0, KEY_QUERY_VALUE, &hKey );
    if( lRet != ERROR_SUCCESS ) {
      goto next_label_3;
    }

    lRet = RegQueryValueEx( hKey, "ProcessorNameString", NULL, NULL, (LPBYTE) szOrigCPUType, &dwBufLen);
    if( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) ) {
      goto next_label_3;
    }
    RegCloseKey( hKey );

    if (strlen(szOrigCPUType)>0) {
      while(szOrigCPUType[i]==' ' && szOrigCPUType[i]!=0)
        i++;

      strcat(buf,szOrigCPUType+i);
    } else
      goto next_label_3;
  } else {
next_label_3:
   if (processorArchitecture==PROCESSOR_ARCHITECTURE_UNKNOWN)
        strcat(buf,"unknown_arch");
   else if (processorArchitecture==PROCESSOR_ARCHITECTURE_INTEL) {
     strcat(buf,"Intel ");
     sprintf(buf2,"level %d ",processorLevel);
     strcat(buf,buf2);
   } else if (processorArchitecture==PROCESSOR_ARCHITECTURE_IA64)
        strcat(buf,"IA64 ");
   else if (processorArchitecture==PROCESSOR_ARCHITECTURE_MIPS)
        strcat(buf,"MIPS ");
   else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA)
        strcat(buf,"Alpha ");
   else if (processorArchitecture==PROCESSOR_ARCHITECTURE_PPC)
        strcat(buf,"PowerPC ");
   else if (processorArchitecture==PROCESSOR_ARCHITECTURE_SHX)
        strcat(buf,"SHX ");
   else if (processorArchitecture==PROCESSOR_ARCHITECTURE_ALPHA64)
        strcat(buf,"Alpha64 ");
   else
        strcat(buf,"unknown_arch ");
  }
 
  strcat(buf,")");

  retval = (*env)->NewStringUTF(env,buf);
  return retval;
}
/* ......................................................................... */






#undef MIN_ELAPSED_TIME

/* ------------------------------------------------------------------------- */
/* end of file */





编写makefile
#    Project: SystemInfo
#    Makefile created by Khan.Lau
#    Write    by 2007-05-16


#    应用程序名
#LIB = SystemInfo.a
DLL =    SystemInfo.dll
#BIN = SystemInfo.exe


#    输出目录
#    CONFIGURATION = debug
CONFIGURATION    =    release

#    取得项目的当前工作路径
PROJECT_PATH = "D:/Project/Cplus/SystemInfo/src"

CPP = g++
CC = gcc
COMPILER = $(CC)

#    c/c++库路径
LIBPATH = "D:/Develop/CPlus/MinGW/lib"

WINDRES = windres.exe
RES =

#    包路径
LIBS = -L$(LIBPATH) \
    -lpsapi

INCS = -I$(LIBPATH)/include \
    -ID:/Develop/Java/jdk1.5.0_02/include \
    -ID:/Develop/Java/jdk1.5.0_02/include/win32 \
    -I$(PROJECT_PATH)

CXXINCS = -I$(LIBPATH)/include \
    -I$(LIBPATH)/include/c++/3.2.3 \
    -I$(LIBPATH)/include/c++/3.2.3/backward \
    -I$(LIBPATH)/include/c++/3.2.3/mingw32 \
    -I$(PROJECT_PATH)

DLLFLAGS = -DBUILD_DLL
CXXFLAGS = $(DLLFLAGS) -g -Wall $(CXXINCS)       
CFLAGS = $(DLLFLAGS) -Wall $(INCS)       

COMPILER_FLAG = $(CFLAGS)

RM = rm -f

LINKOBJ = $(CONFIGURATION)/SystemInfo.o    \
                $(RES)


.PHONY:    all all-before all-after clean clean-custom rebuild   

all: all-before $(DLL) all-after

clean: clean-custom
    ${RM} $(LINKOBJ) $(CONFIGURATION)/$(DLL)   

$(LIB): $(LINKOBJ)
    ar -r $(CONFIGURATION)/$(LIB) $(LINKOBJ)   

$(DLL): $(LINKOBJ)
        $(COMPILER)  -shared -Wl,--add-stdcall-alias  -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)

$(BIN):    $(LINKOBJ)
    $(COMPILER) -o $(CONFIGURATION)/$(BIN) $(LINKOBJ) $(LIBS)

#缩减可执行文件大小
strip:   
    strip    $(CONFIGURATION)/$(LIB)
   

################################################################################

$(CONFIGURATION)/SystemInfo.o: src/dll/SystemInfo.c
    $(COMPILER) -c src/dll/SystemInfo.c -o $(CONFIGURATION)/SystemInfo.o $(COMPILER_FLAG)


################################################################################

rebuild: clean    all



makefile中注意
$(DLL): $(LINKOBJ)
        $(COMPILER)  -shared -Wl,--add-stdcall-alias  -o $(CONFIGURATION)/$(DLL) $(LINKOBJ) $(LIBS)

-shared -Wl,--add-stdcall-alias 这3个参数是一定要的. 具体含义请参阅gcc帮助..
否则会出现如下异常:java.lang.UnsatisfiedLinkError
如果你确认自己的dll名没有错. loadlibrary的名字也没有填错. 那应该就要检查如上部分了

实际发布的时候. 不要使用调试版本. 也就是编译参数不能有-g

ok, 现在make出dll使用吧....


我本地测试的输出结果为 :

getMaxMem:506604
getCPUs:1
getSysInfo:WinXP Service Pack 2 (Build 2600), on A7648944D08843B (Intel level 15 )
SystemInfo.dll is Loaded

posted on 2008-06-23 12:57 Khan 阅读(4834) 评论(0)  编辑 收藏 引用 所属分类: GCC/G++跨平台开发Java


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2006年11月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

导航

统计

常用链接

留言簿(33)

随笔分类(225)

随笔档案(169)

相册

技术

友情链接

最新随笔

搜索

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜