내 접근 방식은 과거에는 가능한 한 적은 코드로 작성하여 작동하도록했습니다. 나는 그것이 작동하도록 코드를 작성해야 할 때 내가 선호의 순서를 쓰기 : C 또는 C와 같은
쓰기 ++에에게 원래의 라이브러리 - 모두가이 코드를 사용할 수 있습니다, 당신은 필요 없어 공급 "접착제"-
대상 언어 더 쓰기 (예를 들어 꿀꺽 꿀꺽 그들에 대해 알고, 사용의 반환 형식을 C++에서 더 많은 과부하를 추가 C에서 함수의 더 많은 버전을 추가) 아무것도 Java 또는 꿀꺽 꿀꺽 특정 쓰기 함께 도서관의 일부 비트를 가져와야합니다. 이 경우에는 Java가됩니다.
이것이 "순수한"Java인지, SWIG 외부인지, 아니면 내 관점에서 SWIG 인터페이스 파일의 일부인지는 중요하지 않습니다. 자바 인터페이스의 사용자는 두 가지를 구별 할 수 없어야합니다. 그러나 SWIG를 사용하여 여러 가지 사례에서 반복을 피할 수 있습니다.
SWIG 형식 맵을 통해 일부 JNI를 작성하십시오. 이것은 당신이 그것을 쓰는 것에 익숙하지 않다면 추악하고, 오류가 발생하기 쉽고, 유지하기가 더 어렵고 (틀림없이) SWIG + Java에만 유용합니다. SWIG typemaps를 사용하면 적어도 랩하는 모든 유형에 대해 한 번만 쓰는 것을 의미합니다.
시간 나는 2 이상이 선호하는 것 중 하나 이상이다
- 이 많이 나오면
- 내가 모든 대상 언어를 모르는 (반복적 인 코드를 저장) 이 경우 언어의 C API를 사용하는 것이 아마도 해당 언어로 된 내용을 쓰는 것보다 쉽습니다.
- 사용자는이 것을 기대합니다
- 또는 이전 스타일을 사용할 수 없습니다.
기본적으로이 가이드 라인은 당신이 작성해야 추가, 대상 언어 특정 코드의 양을 최소화하고 그 때의 복잡성을 감소 동안 가능한 라이브러리의 많은 사용자에게 기능을 제공하려는 제안 당신은 그것을 써야만합니다.sockaddr_in*
의 특정 사례를 들어
:
접근 한
내가 노력하겠다고 및 수행이 포인터보다 더 많은 것을 포장하지 않도록입니다 가장 먼저하는 일. 이것은 기본적으로 sw30이 SWIGTYPE_p_sockaddr_in
일과 함께하는 것입니다. Java에서이 "알 수없는"유형은 매우 유용하게 사용할 수 있습니다. 한 가지만 다른 것으로 전달하거나 컨테이너/멤버로 저장하는 등의 작업 만 수행하면됩니다.
public static void main(String[] argv) {
Module.takes_a_sockaddr(Module.returns_a_sockaddr());
}
C에서, 다른 함수를 쓰기 좋아하는 당신이 뭔가를 할 수있는 일을하지 않는 경우 : 이것은하지만이 경우되지 대단한
const char * sockaddr2host(struct sockaddr_in *in); // Some code to get the host as a string
unsigned short sockaddr2port(struct sockaddr_in *in); // Some code to get the port
- 일부 복잡성을 가지고 주소 패밀리를 다루기 위해서는 주소 패밀리가 필요합니다. (그 이유는 처음에 sockaddr_in
을 사용하는 이유입니다.)하지만 Java에만 한정된 것은 아니며 구문이 명확하지 않으며 모든 예외가 자동으로 발생합니다. 그 여전히 나는 자바의 조금 쓰기에 대해 생각하기 시작 것 충분하지 않은 경우
접근법 2
- 당신은 개인 회원으로 SWIGTYPE_p_sockaddr_in
유형을 숨겨 더 좋은 인터페이스를 노출 수 자신의 Java 유형에 대한 호출을 작성하고, 유형을 구성하는 Java에서 리턴하는 함수에 대한 호출을 랩핑합니다 (예 :
public class MyExtension {
private MyExtension() { }
private SWIGTYPE_p_sockaddr_in detail;
public static MyExtension native_call() {
MyExtension e = new MyExtension();
e.detail = Module.real_native_call();
return e;
}
public void some_call_that_takes_a_sockaddr() {
Module.real_call(detail);
}
}
쓸 SWIG가 없으므로 쓸 JNI가 없습니다. SWIG를 사용하여 %pragma(modulecode)
을 사용하여 실제 모듈 SWIG에서 모든 오버로드를 생성 할 수 있습니다. 이는 Java 사용자에게 더 자연스럽고 (아마도 특별한 경우처럼 보이지는 않지만) 더 이상 복잡하지는 않습니다. 열심히 일하는 것은 여전히 SWIG에 의해 수행되고 있습니다. 이것은 Java 측에서 반복적 인 코딩을 피하는 약간의 닦기를 제공합니다.
접근 방식은 3
이것은 기본적으로 my previous answer의 두 번째 부분이 될 것입니다. 자바 사용자가 보편적으로 느끼고 기분이 좋고 C 라이브러리를 수정할 필요가 없기 때문에 좋다. 본질적으로 typemap은 Java 사용자가 기대하는 것에서 C가 작동하는 것으로 변환하고 어느 쪽도 상대방의 전망에 대해 알지 못하는 JNI 호출을 캡슐화하기위한 클린 - 틱 구문을 제공합니다.
단점은 유지 보수하기가 어렵고 디버깅하기가 어렵다는 점입니다. 제 경험으로 SWIG는 이와 같은 것들에 대한 가파른 학습 곡선을 가지고 있지만, 일단 여러분이 C와 같은 재사용 및 캡슐화를 통해 제공하는 힘과 같은 typemaps를 작성하는 데 너무 많은 노력을 기울이지 않는다면 type-> Java 타입 매핑은 매우 유용하고 강력합니다.
팀에 속해 있지만 SWIG 인터페이스를 실제로 이해하는 유일한 사람이라면 큰 "버스에 치면 어떨까요?" 전체적으로 프로젝트에 영향을줍니다. (아마 당신을 불공평하게 만드는 데 꽤 유용 할 것입니다!)
C 함수에서 반환되는 C 구조체 포인터에 관해이 문제를 해결할 수 있습니까? 일반적으로 SWIG typemap을 지정할 필요가 없도록 C 함수 구조 값을 연결하는 "string"유형을 반환하는 래퍼 C 함수를 추가하겠습니까? 예를 들어 sockaddr_in을 반환하는 것은 처리하기가 약간 어렵습니다.C#에는 C# 클라이언트의 데이터를 쉽게 가져올 수있는 라이브러리에 내장 된 구조에 대한 멋진 포인터가 있지만 Java에서 동일하게 찾을 수는 없습니다. – c12
@ c12 - 각 단계에서 수행하고자하는 작업을 보여주는 업데이트를 추가했습니다. 이것은 왜 "Swig에서 X를 어떻게 감쌀 까?" X를 래핑하는 것이 가능한 2 ~ 3 가지 방법을 제안합니다. – Flexo