我有一個C函數,我想通過SWIG使用Java調用,但我不確定如何處理sockaddr_in C結構。任何人都有關於如何處理sockaddr_in的例子?如何使用SWIG將sockaddr_in C結構映射到Java
1
A
回答
2
實際上,有在包裝上swig.orgsockaddr_in
的一篇文章,雖然它現在看起來略顯陳舊。
基本上他們所做的就是編寫一個函數,爲您創建一個新的sockaddr_in
,爲需要填充的值提供參數,這些值很容易在Java中傳遞。這是一個稍微更新,修剪鏈接的文章的版本:
%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方面:
%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"
基本上這調用的java.net.InetSocketAddress
的getAddress()
和getPort()
方法,並使用結果來創建用於呼叫的struct sockaddr_in
。
注:
- 我不是100%肯定我明白了這裏的字節順序
- 我們應該支持AF_INET6正確太 - 我們就需要檢查給定的
InetSocketAddress
看哪個子類在類型映射本身中。 - 沒有
out
typemap。這基本上是相反的過程,JNI代碼將爲我們創建新的Java對象。 - 斷言是非常醜陋的。
爲了完整這裏還有這個包裹,不涉及的JNI,但編寫Java的一點點的第三種可能的方式。我們所做的是SWIG將第一個示例中的struct sockaddr
包裝起來,但是然後使用sockaddr
包裝的函數返回java.net.InetSocketAddress
對象,並提供一些代碼用於在兩者之間進行轉換。我將用一個「out」類型圖給出一個例子,即從函數返回。
考慮:
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)
)。我們也可以在類型圖中做類似的工作。這不正確地處理AF_INET6
地址 - 我無法找到IPv6地址的InetAddress.getByAddress()
的等效項,所以應該可能存在針對該情況的斷言/例外。
-1
1
我相信有更好的答案,我期待着看到它。但這似乎最初起作用。
在你module.i:
%include "stdint.i"
%{
#include <arpa/inet.h>
%}
struct in_addr {
uint32_t s_addr;
};
struct sockaddr_in {
uint16_t sin_port;
struct in_addr sin_addr;
};
相關問題
- 1. c結構映射到使用SWIG的ruby
- 2. SWIG或Boost -for將C結構映射到Python
- 3. SWIG C++結構到java
- 4. 將SQL錶行映射到C++結構
- 5. 如何memcpy()結構sockaddr_in
- 6. 如何將嵌套的yaml結構映射到Java的ConfigurationProviderBuilder?
- 7. Castor:如何映射Java層次結構
- 8. 如何使用linq將數據映射到類結構?
- 9. 如何使用JavaCpp將函數調用從C++映射到Java?
- 10. 如何使用JPA(Java EE)將XML數據結構映射到數據庫
- 11. 如何用jackson將java映射到csv?
- 12. 如何將Slick結果映射到不同的數據結構?
- 13. 將xml值映射到結構值
- 14. 將數據庫結構映射到nHibernate映射文件
- 15. 將Neo4J結果映射到java對象
- 16. 用Cython映射C++數據結構
- 17. 如何使用SWIG typemaps將結構成員從C++用P/Invoke編組爲C#?
- 18. 如何將這些DCB結構設置從C映射到C#SerialPort類
- 19. 如何使用Swig將數組從Java傳遞到C++?
- 20. 在Java中映射數據結構
- 21. 使用SWIG的Perl中的STL映射
- 22. 如何使用SWIG從C++調用Java?
- 23. Java的映射數據結構
- 24. 將查詢結果映射到Java中的POJO構造函數
- 25. Android/OpenglES2:將Java對象映射到着色器結構中?
- 26. 使用AutoMapper將平面結構映射到對象?
- 27. SWIG和Java:如何將C++指針映射到指向Java對象輸出參數的指針
- 28. 是否有C#數據結構將鍵映射到多個值?
- 29. 將流數據映射到C#中的數據結構
- 30. 將C++映射結構保存到磁盤
你想讓它與現有的'java.net.InetAddress'類兼容,或者只是用一個可用的接口包裝'sockaddr_in'? – Flexo
我想用一個可用的界面來包裝它... – c12