Fix socket example on POSIX (#966)

This commit is contained in:
Nikolay Igotti
2017-10-23 14:15:28 +03:00
committed by GitHub
parent 85a782cd7e
commit 2dde9eda55
11 changed files with 84 additions and 25 deletions
@@ -26,5 +26,6 @@ class InteropConfiguration(
val pkgName: String, val pkgName: String,
val excludedFunctions: Set<String>, val excludedFunctions: Set<String>,
val strictEnums: Set<String>, val strictEnums: Set<String>,
val nonStrictEnums: Set<String> val nonStrictEnums: Set<String>,
val noStringConversion: Set<String>
) )
@@ -57,6 +57,10 @@ class StubGenerator(
val excludedFunctions: Set<String> val excludedFunctions: Set<String>
get() = configuration.excludedFunctions get() = configuration.excludedFunctions
val noStringConversion: Set<String>
get() = configuration.noStringConversion
val platformWStringTypes = setOf("LPCWSTR") val platformWStringTypes = setOf("LPCWSTR")
/** /**
@@ -305,10 +309,11 @@ class StubGenerator(
return false return false
} }
fun representCFunctionParameterAsString(type: Type): Boolean { fun representCFunctionParameterAsString(function: FunctionDecl, type: Type): Boolean {
val unwrappedType = type.unwrapTypedefs() val unwrappedType = type.unwrapTypedefs()
return unwrappedType is PointerType && unwrappedType.pointeeIsConst && return unwrappedType is PointerType && unwrappedType.pointeeIsConst &&
unwrappedType.pointeeType.unwrapTypedefs() == CharType unwrappedType.pointeeType.unwrapTypedefs() == CharType &&
!noStringConversion.contains(function.name)
} }
// We take this approach as generic 'const short*' shall not be used as String. // We take this approach as generic 'const short*' shall not be used as String.
@@ -612,7 +617,7 @@ class StubGenerator(
val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type) val representAsValuesRef = representCFunctionParameterAsValuesRef(parameter.type)
val bridgeArgument = if (representCFunctionParameterAsString(parameter.type)) { val bridgeArgument = if (representCFunctionParameterAsString(func, parameter.type)) {
kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable()) kotlinParameters.add(parameterName to KotlinTypes.string.makeNullable())
bodyGenerator.pushMemScoped() bodyGenerator.pushMemScoped()
"$parameterName?.cstr?.getPointer(memScope)" "$parameterName?.cstr?.getPointer(memScope)"
@@ -310,7 +310,8 @@ private fun processLib(args: Map<String, List<String>>,
pkgName = outKtPkg, pkgName = outKtPkg,
excludedFunctions = excludedFunctions, excludedFunctions = excludedFunctions,
strictEnums = def.config.strictEnums.toSet(), strictEnums = def.config.strictEnums.toSet(),
nonStrictEnums = def.config.nonStrictEnums.toSet() nonStrictEnums = def.config.nonStrictEnums.toSet(),
noStringConversion = def.config.noStringConversion.toSet()
) )
val nativeIndex = buildNativeIndex(library) val nativeIndex = buildNativeIndex(library)
+7
View File
@@ -26,4 +26,11 @@ static int posix_errno() {
// Wrapper to access h_errno variable. // Wrapper to access h_errno variable.
static int posix_h_errno() { static int posix_h_errno() {
return h_errno; return h_errno;
}
static int init_sockets() {
return 0;
}
static void deinit_sockets() {
} }
+7
View File
@@ -26,3 +26,10 @@ static int posix_errno() {
static int posix_h_errno() { static int posix_h_errno() {
return h_errno; return h_errno;
} }
static int init_sockets() {
return 0;
}
static void deinit_sockets() {
}
+7
View File
@@ -62,3 +62,10 @@ static void posix_FD_SET(int bit, fd_set *set) {
static int posix_FD_ISSET(int bit, fd_set *set) { static int posix_FD_ISSET(int bit, fd_set *set) {
return FD_ISSET(bit, set); return FD_ISSET(bit, set);
} }
static int init_sockets() {
return 0;
}
static void deinit_sockets() {
}
+7
View File
@@ -48,3 +48,10 @@ static void posix_FD_SET(int bit, fd_set *set) {
static int posix_FD_ISSET(int bit, fd_set *set) { static int posix_FD_ISSET(int bit, fd_set *set) {
return FD_ISSET(bit, set); return FD_ISSET(bit, set);
} }
static int init_sockets() {
return 0;
}
static void deinit_sockets() {
}
+15 -2
View File
@@ -1,6 +1,8 @@
package = platform.posix package = platform.posix
headers = stdio.h Windef.h Winsock2.h Ws2tcpip.h Ws2def.h io.h math.h headers = stdio.h winsock.h io.h math.h
compilerOpts = -DUNICODE -Wno-incompatible-pointer-types -Wno-deprecated-declarations compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 \
-Wno-incompatible-pointer-types -Wno-deprecated-declarations
noStringConversion = send recv
linkerOpts = -lWs2_32 linkerOpts = -lWs2_32
--- ---
@@ -29,3 +31,14 @@ static void posix_FD_SET(int bit, fd_set *set) {
static int posix_FD_ISSET(int bit, fd_set *set) { static int posix_FD_ISSET(int bit, fd_set *set) {
return FD_ISSET(bit, set); return FD_ISSET(bit, set);
} }
static int init_sockets() {
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
return WSAStartup(wVersionRequested, &wsaData);
}
static void deinit_sockets() {
WSACleanup();
return;
}
+2 -1
View File
@@ -1,6 +1,7 @@
package = platform.windows package = platform.windows
headers = windows.h commctrl.h dwmapi.h shlobj.h shlwapi.h shobjidl.h \ headers = windows.h commctrl.h dwmapi.h shlobj.h shlwapi.h shobjidl.h \
urlmon.h usp10.h uxtheme.h vfw.h wininet.h urlmon.h usp10.h uxtheme.h vfw.h wininet.h winsock2.h ws2tcpip.h ws2def.h
compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 \ compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 \
-Wno-incompatible-pointer-types -Wno-deprecated-declarations -Wno-incompatible-pointer-types -Wno-deprecated-declarations
linkerOpts = -lcomctl32 -lcrypt32 -lshlwapi -lshell32 -limm32 -lusp10 -lwininet linkerOpts = -lcomctl32 -lcrypt32 -lshlwapi -lshell32 -limm32 -lusp10 -lwininet
depends = posix
+23 -17
View File
@@ -25,55 +25,61 @@ fun main(args: Array<String>) {
val port = args[0].toShort() val port = args[0].toShort()
// Initialize sockets in platform-dependent way.
init_sockets()
memScoped { memScoped {
val bufferLength = 100L val buffer = ByteArray(1024)
val buffer = allocArray<ByteVar>(bufferLength) val prefixBuffer = kotlin.text.toUtf8Array("echo: ", 0, 6)
val serverAddr = alloc<sockaddr_in>() val serverAddr = alloc<sockaddr_in>()
val listenFd = socket(AF_INET, SOCK_STREAM, 0) val listenFd = socket(AF_INET, SOCK_STREAM, 0)
.ensureUnixCallResult { it >= 0 } .ensureUnixCallResult("socket") { it >= 0 }
with(serverAddr) { with(serverAddr) {
memset(this.ptr, 0, sockaddr_in.size) memset(this.ptr, 0, sockaddr_in.size)
sin_family = AF_INET.narrow() sin_family = AF_INET.narrow()
sin_addr.s_addr = posix_htons(0).toInt()
sin_port = posix_htons(port) sin_port = posix_htons(port)
} }
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toInt()) bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toInt())
.ensureUnixCallResult { it == 0 } .ensureUnixCallResult("bind") { it == 0 }
listen(listenFd, 10) listen(listenFd, 10)
.ensureUnixCallResult { it == 0 } .ensureUnixCallResult("listen") { it == 0 }
val commFd = accept(listenFd, null, null) val commFd = accept(listenFd, null, null)
.ensureUnixCallResult { it >= 0 } .ensureUnixCallResult("accept") { it >= 0 }
while (true) { buffer.usePinned { pinned ->
val length = read(commFd, buffer, bufferLength) while (true) {
.ensureUnixCallResult { it >= 0 } val length = recv(commFd, pinned.addressOf(0), buffer.size, 0)
.ensureUnixCallResult("read") { it >= 0 }
if (length.toInt() == 0) { if (length == 0) {
break break
} }
write(commFd, buffer, length) send(commFd, prefixBuffer.refTo(0), prefixBuffer.size, 0)
.ensureUnixCallResult { it >= 0 } .ensureUnixCallResult("write") { it >= 0 }
send(commFd, pinned.addressOf(0), length, 0)
.ensureUnixCallResult("write") { it >= 0 }
}
} }
} }
} }
inline fun Int.ensureUnixCallResult(predicate: (Int) -> Boolean): Int { inline fun Int.ensureUnixCallResult(op: String, predicate: (Int) -> Boolean): Int {
if (!predicate(this)) { if (!predicate(this)) {
throw Error(strerror(posix_errno())!!.toKString()) throw Error("$op: ${strerror(posix_errno())!!.toKString()}")
} }
return this return this
} }
inline fun Long.ensureUnixCallResult(predicate: (Long) -> Boolean): Long { inline fun Long.ensureUnixCallResult(op: String, predicate: (Long) -> Boolean): Long {
if (!predicate(this)) { if (!predicate(this)) {
throw Error(strerror(posix_errno())!!.toKString()) throw Error("$op: ${strerror(posix_errno())!!.toKString()}")
} }
return this return this
} }
@@ -72,6 +72,10 @@ class DefFile(val file:File?, val config:DefFileConfig, val manifestAddendProper
properties.getSpaceSeparated("nonStrictEnums") properties.getSpaceSeparated("nonStrictEnums")
} }
val noStringConversion by lazy {
properties.getSpaceSeparated("noStringConversion")
}
val depends by lazy { val depends by lazy {
properties.getSpaceSeparated("depends") properties.getSpaceSeparated("depends")
} }