如何使用SWIG将sockaddr_in C结构映射到Java [英] How to map sockaddr_in C Structure to Java using SWIG

查看:46
本文介绍了如何使用SWIG将sockaddr_in C结构映射到Java的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个C函数,想通过SWIG使用Java调用,但是我不确定如何处理sockaddr_in C结构.任何人都有我如何处理sockaddr_in的示例吗?

I have a C function that I want to call using Java via SWIG but I'm unsure how to handle the sockaddr_in C structure. Anyone have any examples on how I can handle the sockaddr_in?

推荐答案

实际上有一篇文章将 sockaddr_in 包装在

There's actually an article on wrapping sockaddr_in on swig.org, although it looks slightly old now.

基本上,他们所做的就是编写一个函数,该函数为您创建一个新的 sockaddr_in ,并接受需要填充的值作为在Java中易于传递的东西的参数.这是链接文章的略微更新,修整的版本:

Basically what they did was write a function that creates a new sockaddr_in for you, taking arguments for the values that need to be filled in as things that are easy to pass around in Java. This is a slightly updated, trimmed version of the linked article:

%module sock          // Name of our module
%{
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

/* Set some values in the sockaddr_in structure */
struct sockaddr *new_sockaddr_in(short family, unsigned long hostid, int port) {
        struct sockaddr_in *addr;
        addr = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in));
        bzero((char *) addr, sizeof(struct sockaddr_in));
        addr->sin_family = family;
        addr->sin_addr.s_addr = hostid;
        addr->sin_port = htons(port);
        return (struct sockaddr *) addr;
}
%}

// Add these constants
enum {AF_UNIX, AF_INET, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW,
      IPPROTO_UDP, IPPROTO_TCP, INADDR_ANY};

#define  SIZEOF_SOCKADDR  sizeof(struct sockaddr)

// Wrap these functions
struct sockaddr *new_sockaddr_in(short family, unsigned long, int port);


尽管有一种更好的方法将其与SWIG封装在一起,我们可以编写一个类型映射来使用 java.net.InetSocketAddress ,这在接口的Java端会感觉更自然":


There's a nicer way of wrapping this with SWIG though, we can write a typemap to use java.net.InetSocketAddress instead, which will feel far more "natural" on the Java side of the interface:

%typemap(jni) sockaddr_in *ADDR "jobject"
%typemap(jtype) sockaddr_in *ADDR "java.net.InetSocketAddress"
%typemap(jstype) sockaddr_in *ADDR "java.net.InetSocketAddress"

%typemap(in) (sockaddr_in *ADDR) {
  $1 = new sockaddr_in;
  $1->sin_family = AF_INET;
  jclass inetsockaddr = jenv->FindClass("java/net/InetSocketAddress");
  assert(inetsockaddr);
  // TODO: check return
  jmethodID pmid,addrmid,ipbytemid;
  pmid = jenv->GetMethodID(inetsockaddr, "getPort", "()I");
  assert(pmid);
  jint port = jenv->CallIntMethod($input, pmid);
  $1->sin_port = htons(port);
  jclass inetaddr = jenv->FindClass("java/net/InetAddress");
  assert(inetaddr);
  addrmid = jenv->GetMethodID(inetsockaddr, "getAddress", "()Ljava/net/InetAddress;");
  assert(addrmid);
  jobject addrobj = jenv->CallObjectMethod($input, addrmid);
  assert(addrobj);
  ipbytemid = jenv->GetMethodID(inetaddr, "getAddress", "()[B");
  assert(ipbytemid);
  jbyteArray barr = static_cast<jbyteArray>(jenv->CallObjectMethod(addrobj, ipbytemid));
  assert(barr);
  jbyte *bytes = jenv->GetByteArrayElements(barr, 0);
  assert(bytes);
  memcpy(&$1->sin_addr.s_addr, bytes, 4);
  $1->sin_addr.s_addr = htonl($1->sin_addr.s_addr);
  jenv->ReleaseByteArrayElements(barr, bytes, JNI_ABORT); // No changes copied back
}

%typemap(freearg) (sockaddr_in *ADDR) {
  delete $1;
}

%typemap(javain) sockaddr_in *ADDR "$javainput"

基本上,这将调用getAddress()和 getPort()方法/docs/api/java/net/InetSocketAddress.html"rel =" nofollow> java.net.InetSocketAddress 并使用结果创建一个 struct sockaddr_in 进行通话.

Basically this calls the getAddress() and getPort() methods of java.net.InetSocketAddress and uses the result to create a struct sockaddr_in for the call.

注意:

  1. 我不是100%肯定我这里有字节顺序
  2. 我们也应该适当地支持AF_INET6-我们需要检查给定的 InetSocketAddress ,以查看它在类型映射表中属于哪个子类.
  3. 没有 out 类型映射.基本上这是相反的过程,JNI代码将为我们创建新的Java对象.
  4. 断言很难看.
  1. I'm not 100% sure I've got the byte order right here
  2. We ought to support AF_INET6 properly too - we'd need to inspect the given InetSocketAddress to see which sub-class it is in the typemap itself.
  3. There's no out typemap. This is basically the reverse procedure, the JNI code will create new Java objects for us.
  4. The asserts are pretty ugly.


为了完整起见,还有第三种包装方法,不涉及JNI,而是编写一些Java.我们要做的是像第一个示例一样,将SWIG包装为 struct sockaddr ,但随后使包装的使用 sockaddr 的函数返回一个 java.net.InetSocketAddress 对象,并提供一些代码以在两者之间进行转换.我将举一个带有输出"类型映射的示例,即从函数返回.


For completeness there's also a third possible way of wrapping this, which involves no JNI, but writing a little bit of Java. What we do is have SWIG wrap the struct sockaddr as in the first example, but then have the wrapped functions that use sockaddr return a java.net.InetSocketAddress object still and supply some code for converting between the two. I'll give an example with an "out" typemap, i.e. for returning from functions.

给出:

sockaddr_in *make_stuff();

我们可以将其包装为:

%typemap(jstype) sockaddr_in *make_stuff "java.net.InetSocketAddress"
%typemap(javaout) sockaddr_in *make_stuff {
  long cPtr = $jnicall;
  sockaddr_in s = new sockaddr_in(cPtr, true);
  byte[] bytes = new byte[4];
  for (int i = 0; i < 4; ++i) {
    bytes[i] = (byte)s.getAddr(i);
  }
  java.net.InetAddress addr = null;
  try {
    addr = java.net.InetAddress.getByAddress(bytes);
  }
  catch (java.net.UnknownHostException e) {
    return null;
  }
  return new java.net.InetSocketAddress(addr, s.getPort());
}

%immutable;
struct sockaddr_in{
   %rename(family) sin_family;
   short sin_family;
   %extend {
     unsigned short getPort() const {
       return ntohs($self->sin_port);
     }
     char getAddr(int byte) const {
       const char *ptr = reinterpret_cast<const char*>(&$self->sin_addr.s_addr);
       return ptr[byte];
     }
   }
};
%mutable;

void do_stuff(sockaddr_in *ADDR);

我们已经指定了如何直接包装 sockaddr_in 的方法,但是还指示从函数本身返回的结果应该是更合适的Java类型(%typemap(jstype)),并提供了少量Java来执行转换(%typemap(javaout)).我们也可以为typemap做类似的事情.这不能正确处理 AF_INET6 地址-我找不到与IPv6地址等效的 InetAddress.getByAddress(),因此可能应该有一个断言/异常这种情况.

We've specified how to wrap a sockaddr_in directly, but also instructed the return from the function itself to be the more appropriate Java type (%typemap(jstype)) and provided a small amount of Java to perform the conversion (%typemap(javaout)). We could do similar for an in typemap too. This doesn't handle AF_INET6 addresses properly - I can't find an equivalent of InetAddress.getByAddress() for IPv6 addresses, so there should probably be an assert/exception for that case.

这篇关于如何使用SWIG将sockaddr_in C结构映射到Java的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆