Fix socket example on POSIX (#966)
This commit is contained in:
+2
-1
@@ -26,5 +26,6 @@ class InteropConfiguration(
|
||||
val pkgName: String,
|
||||
val excludedFunctions: Set<String>,
|
||||
val strictEnums: Set<String>,
|
||||
val nonStrictEnums: Set<String>
|
||||
val nonStrictEnums: Set<String>,
|
||||
val noStringConversion: Set<String>
|
||||
)
|
||||
+8
-3
@@ -57,6 +57,10 @@ class StubGenerator(
|
||||
val excludedFunctions: Set<String>
|
||||
get() = configuration.excludedFunctions
|
||||
|
||||
val noStringConversion: Set<String>
|
||||
get() = configuration.noStringConversion
|
||||
|
||||
|
||||
val platformWStringTypes = setOf("LPCWSTR")
|
||||
|
||||
/**
|
||||
@@ -305,10 +309,11 @@ class StubGenerator(
|
||||
return false
|
||||
}
|
||||
|
||||
fun representCFunctionParameterAsString(type: Type): Boolean {
|
||||
fun representCFunctionParameterAsString(function: FunctionDecl, type: Type): Boolean {
|
||||
val unwrappedType = type.unwrapTypedefs()
|
||||
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.
|
||||
@@ -612,7 +617,7 @@ class StubGenerator(
|
||||
|
||||
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())
|
||||
bodyGenerator.pushMemScoped()
|
||||
"$parameterName?.cstr?.getPointer(memScope)"
|
||||
|
||||
+2
-1
@@ -310,7 +310,8 @@ private fun processLib(args: Map<String, List<String>>,
|
||||
pkgName = outKtPkg,
|
||||
excludedFunctions = excludedFunctions,
|
||||
strictEnums = def.config.strictEnums.toSet(),
|
||||
nonStrictEnums = def.config.nonStrictEnums.toSet()
|
||||
nonStrictEnums = def.config.nonStrictEnums.toSet(),
|
||||
noStringConversion = def.config.noStringConversion.toSet()
|
||||
)
|
||||
|
||||
val nativeIndex = buildNativeIndex(library)
|
||||
|
||||
@@ -26,4 +26,11 @@ static int posix_errno() {
|
||||
// Wrapper to access h_errno variable.
|
||||
static int posix_h_errno() {
|
||||
return h_errno;
|
||||
}
|
||||
|
||||
static int init_sockets() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_sockets() {
|
||||
}
|
||||
@@ -26,3 +26,10 @@ static int posix_errno() {
|
||||
static int posix_h_errno() {
|
||||
return h_errno;
|
||||
}
|
||||
|
||||
static int init_sockets() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_sockets() {
|
||||
}
|
||||
@@ -62,3 +62,10 @@ static void posix_FD_SET(int bit, fd_set *set) {
|
||||
static int posix_FD_ISSET(int bit, fd_set *set) {
|
||||
return FD_ISSET(bit, set);
|
||||
}
|
||||
|
||||
static int init_sockets() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_sockets() {
|
||||
}
|
||||
@@ -48,3 +48,10 @@ static void posix_FD_SET(int bit, fd_set *set) {
|
||||
static int posix_FD_ISSET(int bit, fd_set *set) {
|
||||
return FD_ISSET(bit, set);
|
||||
}
|
||||
|
||||
static int init_sockets() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_sockets() {
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package = platform.posix
|
||||
headers = stdio.h Windef.h Winsock2.h Ws2tcpip.h Ws2def.h io.h math.h
|
||||
compilerOpts = -DUNICODE -Wno-incompatible-pointer-types -Wno-deprecated-declarations
|
||||
headers = stdio.h winsock.h io.h math.h
|
||||
compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 \
|
||||
-Wno-incompatible-pointer-types -Wno-deprecated-declarations
|
||||
noStringConversion = send recv
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package = platform.windows
|
||||
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 \
|
||||
-Wno-incompatible-pointer-types -Wno-deprecated-declarations
|
||||
linkerOpts = -lcomctl32 -lcrypt32 -lshlwapi -lshell32 -limm32 -lusp10 -lwininet
|
||||
depends = posix
|
||||
|
||||
@@ -25,55 +25,61 @@ fun main(args: Array<String>) {
|
||||
|
||||
val port = args[0].toShort()
|
||||
|
||||
// Initialize sockets in platform-dependent way.
|
||||
init_sockets()
|
||||
|
||||
memScoped {
|
||||
|
||||
val bufferLength = 100L
|
||||
val buffer = allocArray<ByteVar>(bufferLength)
|
||||
val buffer = ByteArray(1024)
|
||||
val prefixBuffer = kotlin.text.toUtf8Array("echo: ", 0, 6)
|
||||
val serverAddr = alloc<sockaddr_in>()
|
||||
|
||||
val listenFd = socket(AF_INET, SOCK_STREAM, 0)
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
.ensureUnixCallResult("socket") { it >= 0 }
|
||||
|
||||
with(serverAddr) {
|
||||
memset(this.ptr, 0, sockaddr_in.size)
|
||||
sin_family = AF_INET.narrow()
|
||||
sin_addr.s_addr = posix_htons(0).toInt()
|
||||
sin_port = posix_htons(port)
|
||||
}
|
||||
|
||||
bind(listenFd, serverAddr.ptr.reinterpret(), sockaddr_in.size.toInt())
|
||||
.ensureUnixCallResult { it == 0 }
|
||||
.ensureUnixCallResult("bind") { it == 0 }
|
||||
|
||||
listen(listenFd, 10)
|
||||
.ensureUnixCallResult { it == 0 }
|
||||
.ensureUnixCallResult("listen") { it == 0 }
|
||||
|
||||
val commFd = accept(listenFd, null, null)
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
.ensureUnixCallResult("accept") { it >= 0 }
|
||||
|
||||
while (true) {
|
||||
val length = read(commFd, buffer, bufferLength)
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
buffer.usePinned { pinned ->
|
||||
while (true) {
|
||||
val length = recv(commFd, pinned.addressOf(0), buffer.size, 0)
|
||||
.ensureUnixCallResult("read") { it >= 0 }
|
||||
|
||||
if (length.toInt() == 0) {
|
||||
if (length == 0) {
|
||||
break
|
||||
}
|
||||
|
||||
write(commFd, buffer, length)
|
||||
.ensureUnixCallResult { it >= 0 }
|
||||
send(commFd, prefixBuffer.refTo(0), prefixBuffer.size, 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)) {
|
||||
throw Error(strerror(posix_errno())!!.toKString())
|
||||
throw Error("$op: ${strerror(posix_errno())!!.toKString()}")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun Long.ensureUnixCallResult(predicate: (Long) -> Boolean): Long {
|
||||
inline fun Long.ensureUnixCallResult(op: String, predicate: (Long) -> Boolean): Long {
|
||||
if (!predicate(this)) {
|
||||
throw Error(strerror(posix_errno())!!.toKString())
|
||||
throw Error("$op: ${strerror(posix_errno())!!.toKString()}")
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@ class DefFile(val file:File?, val config:DefFileConfig, val manifestAddendProper
|
||||
properties.getSpaceSeparated("nonStrictEnums")
|
||||
}
|
||||
|
||||
val noStringConversion by lazy {
|
||||
properties.getSpaceSeparated("noStringConversion")
|
||||
}
|
||||
|
||||
val depends by lazy {
|
||||
properties.getSpaceSeparated("depends")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user