Programing

Java에서 c 함수 호출

c10106 2022. 5. 24. 23:08
반응형

Java에서 c 함수 호출

자바에서 c 함수를 호출하는 방법.c는 컴파일러 기반인 것 같아

자바에서 윈도 C기능을 호출하고, 자바에서도 GCC기능을 호출하고 싶다.

참고할 만한 게 있나?

Java 기본 인터페이스를 살펴보십시오. 시작하기.

2.1 개요

[...] C 함수를 호출하여 "Hello World!"를 인쇄하는 간단한 Java 애플리케이션을 작성한다.프로세스는 다음 단계로 구성된다.

네이티브 메서드를 선언하는 클래스(HelloWorld.java)를 만드십시오.javaclu.docling helloWorld 소layling helloWorld.classmissi를 한다.Javac 컴파일러는 JDK 또는 Java 2 SDK 릴리즈와 함께 제공된다.사용하다javah -jniC 헤더 파일을 생성하려면(HelloWorld.h 기능 는 네이티브 메서드 구현을 위한 기능 프로토타입을 포함한다.자바 도구는 JDK 또는 Java 2 SDK 릴리즈와 함께 제공된다.작성한다(C 구현 기 기 ( ( ( ( ( ( ( (HelloWorld.c의 고유 방법.C 구현을 네이티브 라이브러리로 컴파일하여 작성Hello-World.dll또는libHello-World.so할 수 C 및 호스트 환경에서 사용할 수 있는 C 컴파일러 및 링커를 사용하십시오.Java 런타임 인터프리터를 사용하여 HelloWorld 프로그램을 실행하십시오.두 클래스 파일 모두(HelloWorld.class) 및 기본 라이브러리(HelloWorld.dll또는libHelloWorld.so런타임에 로딩된다.이 장의 나머지 부분에서는 이러한 단계를 상세히 설명한다.

2.2 네이티브 메서드 선언

당신은 자바 프로그래밍 언어로 다음 프로그램을 쓰는 것으로 시작한다.이 프로그램은 HelloWorld라는 이름의 클래스를 정의하는데, 여기에는 네이티브 메서드인 프린트가 포함되어 있다.

class HelloWorld {
    private native void print();

    public static void main(String[] args) {
        new HelloWorld().print();
    }

    static {
        System.loadLibrary("HelloWorld");
    }
}

HelloWorld 클래스 정의는 인쇄 네이티브 메서드의 선언으로 시작한다.이어 헬로월드 클래스를 인스턴스화하고 이 경우 인쇄 네이티브 메소드를 호출하는 메인 메소드가 이어진다.클래스 정의의 마지막 부분은 인쇄 네이티브 메서드의 구현을 포함하는 네이티브 라이브러리를 로드하는 정적 이니셜라이저다.

자바 프로그래밍 언어의 인쇄와 같은 네이티브 메서드의 선언과 정규 메서드의 선언 사이에는 두 가지 차이가 있다.네이티브 메서드 선언에는 네이티브 수식어가 포함되어야 한다.고유 수식어는 이 방법이 다른 언어로 구현되었음을 나타낸다.또한 네이티브 메서드 선언은 클래스 자체에 네이티브 메서드에 대한 구현이 없기 때문에 문종료자 기호인 세미콜론으로 종료된다.우리는 별도의 C파일로 프린트 방법을 실행하겠다.

네이티브 메서드 프린트를 호출하기 전에 먼저 프린트를 구현하는 네이티브 라이브러리를 로드해야 한다.이 경우, 기본 라이브러리를 의 정적 이니셜라이저에 로드한다.HelloWorld 시스템은 한다. Java 가상 시스템은 정적 이니셜라이저를 자동으로 실행한 후HelloWorld따라서 인쇄 네이티브 메서드가 호출되기 전에 네이티브 라이브러리가 로드되는지 확인하십시오.

우리는 주요 방법을 정의하여HelloWorld계급Hello-World.main일반적인 방법이라고 부르는 것과 같은 방식으로 네이티브 메서드 프린트를 호출한다.

System.loadLibrary라이브러리 이름을 가져오고, 해당 이름에 해당하는 네이티브 라이브러리를 찾은 다음, 네이티브 라이브러리를 애플리케이션에 로드한다.정확한 적재 과정은 책 후반부에서 논의하겠다. 기억하기 지만 지만 기기만 하면 을 기억하기 바란다.System.loadLibrary("HelloWorld")성공하기 위해서, 우리는 "라고 불리는 토착 도서관을 만들어야 한다.HelloWorld.dll,즉에 는libHelloWorld.so솔라리스에서.

2.3 HelloWorld 클래스 컴파일

HelloWorld 클래스를 정의한 후 HelloWorld.java라는 파일에 소스 코드를 저장하십시오.그런 다음 JDK 또는 Java 2 SDK 릴리스와 함께 제공되는 javac 컴파일러를 사용하여 원본 파일을 컴파일하십시오.

 javac HelloWorld.java

HelloWorld.class파일을 현재 디렉터리에 저장하십시오.

2.4 Native Method 헤더 파일 생성

다음으로, 우리는 다음 제품을 사용할 것이다.javahC에서 네이티브 메서드를 구현할 때 유용한 JNI 스타일 헤더 파일을 생성하는 도구.너는 달릴 수 있다.javah에서Hello-World다음과 같이 분류한다.

  javah -jni HelloWorld

헤더 파일의 이름은 "을(를) 가진 클래스 이름이다..h"끝에 덧붙인다.위에 표시된 명령은 이름이 지정된 파일을 생성함HelloWorld.h생성된 헤더 파일 전체를 여기에 나열하지 않는다.헤더 파일의 가장 중요한 부분은 기능 프로토타입이다.Java_HelloWorld_print HelloWorld.print 은 C 함canable이다.

 JNIEXPORT void JNICALL   Java_HelloWorld_print (JNIEnv *, jobject);

무시 JNIEXPORT, 그리고JNICALL日本語로. 본래의 방법이 어떠한 본래의 의 C 을 받아들인다는 원주민 방법의 상응하는 선언이 어떤 주장을 받아들이지 않더라도 원주민 방법의 C 구현은 두 가지 주장을 수용한다는 것을 눈치챘을 것이다.모든 기본 방법 구현에 대한 첫 번째 주장은JNIEnv인터페이스 포인터두 번째 주장은 에 대한 언급이다.HelloWorld물체 그 자체 ("와 같은 의미)this" 포인터는 C++).우리는 어떻게 사용할 것인지에 대해 토론할 것이다.JNIEnv인터페이스 포인터 및jobject이 책의 뒷부분의 논쟁, 그러나 이 간단한 예는 두 주장 모두를 무시한다.

2.5 네이티브 메서드 구현 기록

다음에 의해 생성된 JNI 스타일 헤더 파일javah기본 방법에 대한 C 또는 C++ 구현을 작성할 수 있도록 지원하십시오.작성하는 기능은 생성 헤더 파일에 지정된 -prototype을 따라야 한다.다음 작업을 수행할 수 있다.Hello-World.printC파일의 방법HelloWorld.c아래와 같이

#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"   

JNIEXPORT void JNICALL   Java_HelloWorld_print(JNIEnv *env, jobject obj)  {
     printf("Hello World!\n");
     return;
}

이 토착적 방법의 실행은 간단하다.프린트 f 기능을 사용해 "Hello World!"라는 문자열을 표시한 뒤 돌아온다.앞서 언급한 바와 같이 두 주장 모두.JNIEnv포인터 및 객체에 대한 참조는 무시된다.

C 프로그램은 다음과 같은 세 개의 헤더 파일을 포함한다.

jni.h-- 이 헤더 파일은 네이티브 코드가 JNI 기능을 호출하는 데 필요한 정보를 제공한다.기본 메서드를 작성할 때 항상 이 파일을 C 또는 C++ 소스 파일에 포함시켜야 한다. stdio.h-- 위의 코드 조각은 또한 다음을 포함한다.stdio.h왜냐하면 그것은 그것을 사용하기 때문이다.printf기능을 발휘하다 HelloWorld.h-- 다음을 사용하여 생성한 헤더 파일javah. 를 위한 C/C++ 프로토타입을 포함한다.Java_HelloWorld_print기능. 2.6 C 소스 컴파일 및 네이티브 라이브러리 생성

때 기억하라.HelloWorldHelloWorld.java파일에 기본 라이브러리를 로드한 코드 줄을 프로그램에 포함:

 System.loadLibrary("HelloWorld");   

필요한 C 코드가 모두 작성되었으므로, 이제 컴파일을 해야 한다.Hello-World.c그리고 이 토착 도서관을 짓는다.

서로 다른 운영 체제는 네이티브 라이브러리를 구축하는 다양한 방법을 지원한다.Solaris에서 다음 명령은 libHello-World.so이라는 공유 라이브러리를 빌드한다.

 cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so

-G 옵션은 C 컴파일러가 일반 Solaris 실행 파일 대신 공유 라이브러리를 생성하도록 지시한다.이 책의 페이지 너비의 한계 때문에 우리는 명령줄을 두 줄로 끊어 버린다.명령을 한 줄에 입력하거나 스크립트 파일에 넣으십시오.위에Win32, 다음 명령은 동적 링크 라이브러리(DLL)를 빌드한다.HelloWorld.dllMicrosoft Visual C++ 컴파일러 사용:

 cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll 

-MD옵션으로 다음 작업을 수행할 수 있음HelloWorld.dll와 연결되어 있다Win32다중 스레드 C 라이브러리.-LD옵션은 C 컴파일러가 일반 Win32 실행 파일 대신 DLL을 생성하도록 지시한다.물론 Solaris와 Win32 둘 다 자신의 컴퓨터에 설정을 반영하는 경로를 포함시켜야 한다.

2.7 프로그램 실행

이 시점에서 프로그램을 실행할 두 구성 요소를 준비하십시오.클래스 파일(HelloWorld.class)은 네이티브 메서드를 호출하고, 네이티브 라이브러리(Hello-World.dll)는 네이티브 메서드를 구현한다.

왜냐하면HelloWorld클래스에 자체 메인 메서드가 포함되어 있으며, 다음과 같이 Solaris 또는 Win32에서 프로그램을 실행할 수 있다.

 java HelloWorld

다음 출력을 확인하십시오.

   Hello World! 

프로그램이 실행되려면 기본 라이브러리 경로를 올바르게 설정하는 것이 중요하다.네이티브 라이브러리 경로는 네이티브 라이브러리를 로드할 때 자바 가상 시스템이 검색하는 디렉터리 목록이다.기본 라이브러리 경로를 올바르게 설정하지 않은 경우 다음과 유사한 오류가 표시됨:

 java.lang.UnsatisfiedLinkError: no HelloWorld in library path
         at java.lang.Runtime.loadLibrary(Runtime.java)
         at java.lang.System.loadLibrary(System.java)
         at HelloWorld.main(HelloWorld.java) 

기본 라이브러리가 기본 라이브러리 경로의 디렉토리 중 하나에 있는지 확인하십시오.Solaris 시스템에서 실행 중인 경우LD_LIBRARY_PATH환경변수는 기본 라이브러리 경로를 정의하는 데 사용된다.이 디렉터리에 다음 디렉터리가 들어 있는지 확인하십시오.libHelloWorld.so파일을 작성. 만약libHelloWorld.so파일이 현재 디렉터리에 있으며 표준 셸(sh) 또는 KornShell(ksh)에서 다음 두 개의 명령을 실행하여LD_LIBRARY_PATH환경 변수 올바르게:

 LD_LIBRARY_PATH=.
 export LD_LIBRARY_PATH

C 셸(csh 또는 tcsh)의 등가 명령어는 다음과 같다.

 setenv LD_LIBRARY_PATH .

Windows 95 또는 Windows NT 시스템에서 실행 중인 경우HelloWorld.dll현재 디렉터리에 있거나 PATH 환경 변수에 나열된 디렉터리에 있음.

Java 2 SDK 1.2 릴리스에서는 다음과 같이 자바 명령줄의 네이티브 라이브러리 경로를 시스템 속성으로 지정할 수도 있다.

 java -Djava.library.path=. HelloWorld

The "-D" 명령줄 옵션은 Java 플랫폼 시스템 속성을 설정한다.설정java.library.path"에 대한 재산.."는 자바 가상 머신이 현재 디렉토리의 네이티브 라이브러리를 검색하도록 지시한다.

이항 범주에서 C에서 Mips로 컴파일하고 JVM 내에서 Mips VM을 실행하는 중첩된 VM을 참조하십시오.

http://nestedvm.ibex.org/

간단히 말해 함수 정의가 포함된 관련 라이브러리를 로드하고 JNI 사양에 따라 대상 함수를 첫 번째 라이브러리에서 랩으로 감싸는 라이브러리를 로드하고 Java 클래스에서 기본 메서드를 노출하면 바로 사용할 수 있다.

나는 생 JNI에 대해 추천하고 싶다. 왜냐하면 그것은 많은 보일러 코드를 포함하고 있고 만약 당신이 큰 C 라이브러리를 포장하기 시작하면 당신은 결국 자신을 욕하게 될 것이기 때문이다.물론 시작할 때는 자유롭게 JNI에 손을 대지만 실제 업무에 있어서는 JNA와 같은 것을 사용해라.

@Jonas는 매우 정교한 답변을 주었지만, 나는 또한 이 웹사이트를 확인할 가치가 있다고 생각한다. 그리고 당신은 그곳에서 모든 필수적인 답변을 얻을 것이다.

http://www.ntu.edu.sg/home/ehchua/programming/java/javanativeinterface.html

JNI를 사용하여 프로그램을 호출하는 방법을 설명한다.

  • C 언어와 C++ 또는 둘 다 혼합된 언어의 경우
  • 파라미터, 원시 요소, 문자열 또는 원시 요소 배열 없이 JNI
  • 개체 변수, 콜백 인스턴스 메서드 등에 액세스.

옵션에는 다음이 포함된다.

자바 네이티브 인터페이스
https://en.wikipedia.org/wiki/Java_Native_Interface을 참조하십시오.

인용:

JNI는 표준 Java 클래스 라이브러리가 플랫폼별 기능이나 프로그램 라이브러리를 지원하지 않는 경우와 같이 애플리케이션이 Java 프로그래밍 언어로 완전히 작성될 수 없는 상황을 처리할 수 있는 기본적인 방법을 프로그래머가 작성할 수 있도록 한다.

Java 네이티브 액세스

https://en.wikipedia.org/wiki/Java_Native_Access을 참조하십시오.

인용:

Java Native Access는 Java 프로그램이 Java Native Interface를 사용하지 않고도 네이티브 공유 라이브러리에 쉽게 접근할 수 있도록 하는 커뮤니티 개발 라이브러리다.

JNR-FFI

https://github.com/jnr/jnr-ffi을 참조하십시오.

인용:

jnr-ffi는 손으로 JNI 코드를 작성하지 않고, 또는 SWIG 등의 도구를 사용하지 않고 네이티브 라이브러리를 로드하기 위한 자바 라이브러리다.

체크아웃 JNAerator.https://code.google.com/p/jnaerator/

소스 코드와 전처리기 정의 등을 제공해야 한다.

Windows 및 MinGW gcc를 사용하는 경우 lib의 특정 메서드에 대해 UnsencedLinkError를 받는 경우 추가 플래그가 필요할 수 있다.

gcc -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"%JAVA_HOME%"\include -I"%JAVA_HOME%"\include\win32 BestCode.c -shared -o BestCode.dll

나는 이 문제에 대한 해결책을 얻었다.64비트 C++ 컴파일러를 사용하여 64비트 JRE에서 실행되는 Java 함수를 호출하는 코드를 컴파일러로 컴파일러로 컴파일하고 있는지 확인하십시오.이와 함께 생성된 dll 파일의 경로를 "환경 변수" 아래의 "경로"에 저장해야 한다.

먼저 속성에서 경로를 설정하여 기본 라이브러리 또는 .dll 파일을 클래스 경로에 로드하십시오.java.library.path

그 다음 사용System.loadLibrary()

Do not use .dll extension at the end.

64비트 호환 dll을 만드는 경우 아래 문에서 "-MD" 옵션 제거

cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll

참조URL: https://stackoverflow.com/questions/5963266/call-c-function-from-java

반응형