From e9e931fe4a45e72d1d78385eda320caf8cdb34ff Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 24 Nov 2019 06:27:02 +0300 Subject: [PATCH] force C function definitions --- 0.2_roadmap.txt | 3 +- vlib/builtin/builtin.v | 1 + vlib/builtin/cfns.v | 61 ++++++++++++++++ vlib/builtin/string.v | 1 + vlib/clipboard/clipboard_darwin.v | 2 + vlib/compiler/fn.v | 4 +- vlib/compiler/parser.v | 18 +++-- vlib/compiler/x64/elf.v | 2 +- vlib/crypto/rand/rand_mac.v | 2 + vlib/eventbus/params.v | 3 + vlib/freetype/freetype.v | 4 ++ vlib/gl/1shader.v | 5 ++ vlib/http/backend_nix.v | 114 ++++++++++++++++++------------ vlib/json/json_primitives.v | 7 ++ vlib/math/math.v | 1 + vlib/net/net.v | 4 +- vlib/net/socket.v | 54 +++++++++----- vlib/os/os.v | 5 ++ vlib/os/os_nix.v | 6 +- vlib/sqlite/sqlite.v | 5 ++ vlib/stbi/stbi.v | 4 ++ vlib/sync/sync_nix.v | 5 ++ 22 files changed, 227 insertions(+), 84 deletions(-) diff --git a/0.2_roadmap.txt b/0.2_roadmap.txt index c3f69148da..63fb5201c3 100644 --- a/0.2_roadmap.txt +++ b/0.2_roadmap.txt @@ -19,6 +19,7 @@ + bring back generics - bring back forum/blog and vpm - wrap up orm ++ bring back vweb - fix vorum, migrate to orm - wrap up memory management - remove all compiler memory leaks @@ -42,6 +43,6 @@ + bare metal support + inline assembly + x64 machine code generation (ELF) -- require implicit C.fn definitions, add all missing definitions +- require explicit C.fn definitions, add all missing definitions diff --git a/vlib/builtin/builtin.v b/vlib/builtin/builtin.v index 8d2cad8b10..5399ae11bf 100644 --- a/vlib/builtin/builtin.v +++ b/vlib/builtin/builtin.v @@ -132,6 +132,7 @@ TODO print_backtrace() #endif */ +free(C.malloc(n)) ptr := C.malloc(n) if isnil(ptr) { panic('malloc($n) failed') diff --git a/vlib/builtin/cfns.v b/vlib/builtin/cfns.v index 03348b9b5a..862a7d1470 100644 --- a/vlib/builtin/cfns.v +++ b/vlib/builtin/cfns.v @@ -29,6 +29,66 @@ fn C.realpath(byteptr, byteptr) &char + +fn C.chmod(byteptr, int) +fn C.printf(byteptr, ...byteptr) +fn C.fputs(byteptr) +fn C.fflush(byteptr) int +// TODO define args in these functions +fn C.fseek() int +fn C.fopen() int +fn C.fwrite() int +fn C.fclose() int +fn C.pclose() int +fn C.system() int +fn C.setenv() int +fn C.unsetenv() int +fn C.access() int +fn C.remove() int +fn C.rmdir() int +fn C.chdir() int +fn C.fread() int +fn C.rewind() int +fn C.stat() int +fn C.rename() int +fn C.fgets() int +fn C.memset() int +fn C.sigemptyset() int +fn C.getcwd() int +fn C.signal() int +fn C.mktime() int +fn C.gettimeofday() int +fn C.sleep() int +fn C.usleep() int +fn C.opendir() voidptr +fn C.closedir() int +fn C.mkdir() int +fn C.srand() int +fn C.atof() int +fn C.tolower() int +fn C.toupper() int +fn C.getchar() int +fn C.strerror() *C.char +fn C.snprintf() int +fn C.fprintf(byteptr, ...byteptr) + +fn C.WIFEXITED() bool +fn C.WEXITSTATUS() int +fn C.WIFSIGNALED() bool +fn C.WTERMSIG() int +fn C.DEFAULT_LE() bool +fn C.DEFAULT_EQ() bool +fn C.DEFAULT_GT() bool +fn C.DEFAULT_EQUAL() bool +fn C.DEFAULT_NOT_EQUAL() bool +fn C.DEFAULT_LT() bool +fn C.DEFAULT_GE() bool +fn C.isatty() int + + + + + // Windows fn C._setmode(int, int) fn C._fileno(int) int @@ -42,3 +102,4 @@ fn C.ReadFile(hFile voidptr, lpBuffer voidptr, nNumberOfBytesToRead u32, lpNumbe fn C.GetFileAttributesW(lpFileName byteptr) u32 fn C.RegQueryValueExW(hKey voidptr, lpValueName &u16, lpReserved &u32, lpType &u32, lpData byteptr, lpcbData &u32) int fn C.RegOpenKeyExW(hKey voidptr, lpSubKey &u16, ulOptions u32, samDesired u32, phkResult voidptr) int +fn C.RemoveDirectory() int diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 9d3e24aab9..1c0a4e0c1a 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -95,6 +95,7 @@ pub fn tos2(s byteptr) string { } } +// Same as `tos2`, but for char*, to avoid warnings pub fn tos3(s *C.char) string { if s == 0 { panic('tos3: nil string') diff --git a/vlib/clipboard/clipboard_darwin.v b/vlib/clipboard/clipboard_darwin.v index 06ca6e2dfd..7fc75d510f 100644 --- a/vlib/clipboard/clipboard_darwin.v +++ b/vlib/clipboard/clipboard_darwin.v @@ -37,6 +37,8 @@ fn (cb &Clipboard) has_ownership() bool { return false } +fn C.OSAtomicCompareAndSwapLong() + fn (cb &Clipboard) set_text(text string) bool { #NSString *ns_clip; mut ret := false diff --git a/vlib/compiler/fn.v b/vlib/compiler/fn.v index c498dfde4e..8b59ef246e 100644 --- a/vlib/compiler/fn.v +++ b/vlib/compiler/fn.v @@ -1266,7 +1266,7 @@ fn replace_generic_type(gen_type string, ti &TypeInst) string { args_r << replace_generic_type(arg, ti) } mut t := 'fn (' + args_r.join(',') + ')' - if ret_t.len > 0 { + if ret_t.len > 0 { t += ' ' + replace_generic_type(ret_t, ti) } typ = t @@ -1379,7 +1379,7 @@ fn (p mut Parser) register_multi_return_stuct(types []string) string { return typ } -// save the tokens for the generic funciton body (between `{}`) +// save the tokens for the generic funciton body (between `{}`) // the function signature isn't saved, it is reconstructed from Fn fn (p mut Parser) save_generic_tmpl(f mut Fn, pos int) { mut cbr_depth := 1 diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index ce81b30211..792b603d2c 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -1555,8 +1555,6 @@ fn (p mut Parser) get_const_type(name string, is_ptr bool) string { } fn (p mut Parser) get_c_func_type(name string) string { - //p.warn(name + ' ' + p.expected_type) - //} f := Fn { name: name is_c: true @@ -1564,15 +1562,15 @@ fn (p mut Parser) get_c_func_type(name string) string { p.is_c_fn_call = true p.fn_call(mut f, 0, '', '') p.is_c_fn_call = false - // Try looking it up. Maybe its defined with "C.fn_name() fn_type", - // then we know what type it returns + // C functions must be defined with `C.fn_name() fn_type` cfn := p.table.find_fn(name) or { - // Not Found? Return 'void*' - //return 'cvoid' //'void*' - //if p.expected_type != '' && p.expected_type != 'void' { - //p.warn('\n e=$p.expected_type define imported C function with ' + - //'`fn C.$name([args]) [return_type]`\n') - //} + // Is the user trying to do `var := C.foo()` or `bar(C.foo())` + // without declaring `foo`? + // Do not allow it. + if !name.starts_with('gl') && !name.starts_with('glad') { + p.error('undefined C function `$f.name`\n' + + 'define it with `fn C.$name([args]) [return_type]`') + } return 'void*' } // println("C fn $name has type $cfn.typ") diff --git a/vlib/compiler/x64/elf.v b/vlib/compiler/x64/elf.v index 04dbd62949..277de86dd6 100644 --- a/vlib/compiler/x64/elf.v +++ b/vlib/compiler/x64/elf.v @@ -89,7 +89,7 @@ pub fn (g mut Gen) generate_elf_footer() { g.write64_at(file_size, g.file_size_pos+8) // Create the binary f := os.create(g.out_name) or { panic(err) } - C.chmod(g.out_name.str, 0775) + os.chmod(g.out_name, 0775) f.write_bytes(g.buf.data, g.buf.len) f.close() println('x64 elf binary has been successfully generated') diff --git a/vlib/crypto/rand/rand_mac.v b/vlib/crypto/rand/rand_mac.v index ad0b14ddc6..ff4e876b89 100644 --- a/vlib/crypto/rand/rand_mac.v +++ b/vlib/crypto/rand/rand_mac.v @@ -8,6 +8,8 @@ module rand #flag darwin -framework Security +fn C.SecRandomCopyBytes() int + pub fn read(bytes_needed int) ?[]byte { mut buffer := malloc(bytes_needed) status := C.SecRandomCopyBytes(0, bytes_needed, buffer) diff --git a/vlib/eventbus/params.v b/vlib/eventbus/params.v index 160791ba3c..13c527146f 100644 --- a/vlib/eventbus/params.v +++ b/vlib/eventbus/params.v @@ -43,6 +43,8 @@ pub fn get_array(p Params, name string, def T) []T { return [] } +fn C.map_set() // TODO remove hack + // TODO: make this a method after generics are fixed. pub fn get_map(p Params, name string, valueTyp T) map[string]T { param, _ := p.get_param(name, "") @@ -55,6 +57,7 @@ pub fn get_map(p Params, name string, valueTyp T) map[string]T { keys = C.new_array_from_c_array_no_alloc(len, len, sizeof(T), param.keys) for i, key in keys { //the most simple way to set map value without knowing the typ + // TODO remove C.map_set(&ret, key, param.value + i * sizeof(T)) } } diff --git a/vlib/freetype/freetype.v b/vlib/freetype/freetype.v index d7580a3ef1..e1649c94f6 100644 --- a/vlib/freetype/freetype.v +++ b/vlib/freetype/freetype.v @@ -34,6 +34,10 @@ import ( #include "ft2build.h" #include FT_FREETYPE_H +fn C.FT_Init_FreeType() voidptr +fn C.FT_New_Face() voidptr +fn C.FT_Set_Pixel_Sizes() + const ( diff --git a/vlib/gl/1shader.v b/vlib/gl/1shader.v index 8cfc0edec0..74a2598deb 100644 --- a/vlib/gl/1shader.v +++ b/vlib/gl/1shader.v @@ -153,6 +153,11 @@ pub fn (s Shader) use() { gl.use_program(s.program_id) } +fn C.glGetUniformLocation() int +fn C.glUniformMatrix4fv() +fn C.glUniform1i() +fn C.glUniform3f() + pub fn (s Shader) uni_location(key string) int { return C.glGetUniformLocation(s.program_id, key.str) } diff --git a/vlib/http/backend_nix.v b/vlib/http/backend_nix.v index cc8163932b..d871e0c2fc 100644 --- a/vlib/http/backend_nix.v +++ b/vlib/http/backend_nix.v @@ -4,7 +4,7 @@ module http -import strings +import strings // On linux, prefer a localy build openssl, because it is // much more likely for it to be newer, than the system @@ -24,67 +24,87 @@ import strings #include struct C.SSL { - -} + +} + +fn C.SSL_library_init() +fn C.TLSv1_2_method() voidptr +fn C.SSL_CTX_set_options() +fn C.SSL_CTX_new() voidptr +fn C.SSL_CTX_set_verify_depth() +fn C.SSL_CTX_load_verify_locations() int +fn C.BIO_new_ssl_connect() voidptr +fn C.BIO_set_conn_hostname() int +fn C.BIO_get_ssl() +fn C.SSL_set_cipher_list() int +fn C.BIO_do_connect() int +fn C.BIO_do_handshake() int +fn C.SSL_get_peer_certificate() int +fn C.SSL_get_verify_result() int +fn C.SSL_set_tlsext_host_name() int +fn C.BIO_puts() +fn C.BIO_read() +fn C.BIO_free_all() +fn C.SSL_CTX_free() fn init() int { - C.SSL_library_init() + C.SSL_library_init() return 1 } fn (req &Request) ssl_do(port int, method, host_name, path string) ?Response { - //ssl_method := C.SSLv23_method() - ssl_method := C.TLSv1_2_method() - if isnil(method) { - } - ctx := C.SSL_CTX_new(ssl_method) - if isnil(ctx) { - } - C.SSL_CTX_set_verify_depth(ctx, 4) - flags := C.SSL_OP_NO_SSLv2 | C.SSL_OP_NO_SSLv3 | C.SSL_OP_NO_COMPRESSION - C.SSL_CTX_set_options(ctx, flags) - mut res := C.SSL_CTX_load_verify_locations(ctx, 'random-org-chain.pem', 0) + //ssl_method := C.SSLv23_method() + ssl_method := C.TLSv1_2_method() + if isnil(method) { + } + ctx := C.SSL_CTX_new(ssl_method) + if isnil(ctx) { + } + C.SSL_CTX_set_verify_depth(ctx, 4) + flags := C.SSL_OP_NO_SSLv2 | C.SSL_OP_NO_SSLv3 | C.SSL_OP_NO_COMPRESSION + C.SSL_CTX_set_options(ctx, flags) + mut res := C.SSL_CTX_load_verify_locations(ctx, 'random-org-chain.pem', 0) if res != 1 { - } - web := C.BIO_new_ssl_connect(ctx) - if isnil(ctx) { - } + } + web := C.BIO_new_ssl_connect(ctx) + if isnil(ctx) { + } addr := host_name + ':' + port.str() - res = C.BIO_set_conn_hostname(web, addr.str) + res = C.BIO_set_conn_hostname(web, addr.str) if res != 1 { - } - ssl := &C.SSL{!} - C.BIO_get_ssl(web, &ssl) - if isnil(ssl) { - } - preferred_ciphers := 'HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4' - res = C.SSL_set_cipher_list(ssl, preferred_ciphers.str) + } + ssl := &C.SSL{!} + C.BIO_get_ssl(web, &ssl) + if isnil(ssl) { + } + preferred_ciphers := 'HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4' + res = C.SSL_set_cipher_list(ssl, preferred_ciphers.str) if res != 1 { - } - res = C.SSL_set_tlsext_host_name(ssl, host_name.str) - res = C.BIO_do_connect(web) - res = C.BIO_do_handshake(web) - cert := C.SSL_get_peer_certificate(ssl) - res = C.SSL_get_verify_result(ssl) + } + res = C.SSL_set_tlsext_host_name(ssl, host_name.str) + res = C.BIO_do_connect(web) + res = C.BIO_do_handshake(web) + cert := C.SSL_get_peer_certificate(ssl) + res = C.SSL_get_verify_result(ssl) /////// s := req.build_request_headers(method, host_name, path) - C.BIO_puts(web, s.str) - mut sb := strings.new_builder(100) + C.BIO_puts(web, s.str) + mut sb := strings.new_builder(100) for { - buff := [1536]byte - len := int(C.BIO_read(web, buff, 1536) ) - if len > 0 { - sb.write(tos(buff, len)) - } + buff := [1536]byte + len := int(C.BIO_read(web, buff, 1536) ) + if len > 0 { + sb.write(tos(buff, len)) + } else { - break - } - } - if !isnil(web) { + break + } + } + if !isnil(web) { C.BIO_free_all(web) - } - if !isnil(ctx) { - C.SSL_CTX_free(ctx) + } + if !isnil(ctx) { + C.SSL_CTX_free(ctx) } return parse_response(sb.str()) diff --git a/vlib/json/json_primitives.v b/vlib/json/json_primitives.v index bd4bf05fc7..81f4a1e4ee 100644 --- a/vlib/json/json_primitives.v +++ b/vlib/json/json_primitives.v @@ -97,6 +97,13 @@ fn jsdecode_string(root &C.cJSON) string { return tos_clone(root.valuestring)// , _strlen(root.valuestring)) } +fn C.cJSON_IsTrue() bool +fn C.cJSON_CreateNumber() &C.cJSON +fn C.cJSON_CreateBool() &C.cJSON +fn C.cJSON_CreateString() &C.cJSON +fn C.cJSON_Parse() &C.cJSON +fn C.cJSON_PrintUnformatted() byteptr + fn jsdecode_bool(root &C.cJSON) bool { if isnil(root) { return false diff --git a/vlib/math/math.v b/vlib/math/math.v index bc6ee382c7..1a908ec7fb 100644 --- a/vlib/math/math.v +++ b/vlib/math/math.v @@ -28,6 +28,7 @@ fn C.lgamma(x f64) f64 fn C.pow(x f64, y f64) f64 fn C.round(x f64) f64 fn C.sin(x f64) f64 +fn C.sinh(x f64) f64 fn C.sqrt(x f64) f64 fn C.tgamma(x f64) f64 fn C.tan(x f64) f64 diff --git a/vlib/net/net.v b/vlib/net/net.v index b6dfca6599..97534d6078 100644 --- a/vlib/net/net.v +++ b/vlib/net/net.v @@ -1,6 +1,8 @@ module net -// hostname returns the host name reported by the kernel. +fn C.gethostname() int + +// hostname returns the host name reported by the kernel. pub fn hostname() ?string { mut name := [256]byte // https://www.ietf.org/rfc/rfc1035.txt diff --git a/vlib/net/socket.v b/vlib/net/socket.v index 7387c6c96b..81bea608d4 100644 --- a/vlib/net/socket.v +++ b/vlib/net/socket.v @@ -36,15 +36,31 @@ mut: } struct C.sockaddr_storage {} +fn C.socket() int +fn C.setsockopt() int +fn C.htonl() int +fn C.htons() int +fn C.bind() int +fn C.listen() int +fn C.accept() int +fn C.getaddrinfo() int +fn C.connect() int +fn C.send() int +fn C.recv() int +fn C.read() int +fn C.shutdown() int +fn C.close() int +fn C.ntohs() int +fn C.getsockname() int // create socket -pub fn socket(family int, _type int, proto int) ?Socket { +pub fn new_socket(family int, _type int, proto int) ?Socket { sockfd := C.socket(family, _type, proto) one:=1 // This is needed so that there are no problems with reusing the // same port after the application exits. - C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, sizeof(int)) + C.setsockopt(sockfd, C.SOL_SOCKET, C.SO_REUSEADDR, &one, 4)//sizeof(int)) if sockfd == 0 { return error('net.socket: failed') } @@ -58,16 +74,16 @@ pub fn socket(family int, _type int, proto int) ?Socket { } pub fn socket_udp() ?Socket { - return socket(C.AF_INET, C.SOCK_DGRAM, C.IPPROTO_UDP) + return new_socket(C.AF_INET, C.SOCK_DGRAM, C.IPPROTO_UDP) } // set socket options pub fn (s Socket) setsockopt(level int, optname int, optvalue &int) ?int { - res := C.setsockopt(s.sockfd, level, optname, optvalue, C.sizeof(optvalue)) + res := C.setsockopt(s.sockfd, level, optname, optvalue, sizeof(int)) if res < 0 { return error('net.setsocketopt: failed with $res') } - return int(res) + return res } // bind socket to port @@ -77,7 +93,7 @@ pub fn (s Socket) bind(port int) ?int { addr.sin_port = C.htons(port) addr.sin_addr.s_addr = C.htonl(C.INADDR_ANY) size := 16 // sizeof(C.sockaddr_in) - res := int(C.bind(s.sockfd, &addr, size)) + res := C.bind(s.sockfd, &addr, size) if res < 0 { return error('net.bind: failed with $res') } @@ -87,7 +103,7 @@ pub fn (s Socket) bind(port int) ?int { // put socket into passive mode and wait to receive pub fn (s Socket) listen() ?int { backlog := 128 - res := int(C.listen(s.sockfd, backlog)) + res := C.listen(s.sockfd, backlog) if res < 0 { return error('net.listen: failed with $res') } @@ -107,7 +123,7 @@ pub fn (s Socket) listen_backlog(backlog int) ?int { if res < 0 { return error('net.listen_backlog: failed with $res') } - return int(res) + return res } // helper method to create, bind, and listen given port number @@ -115,7 +131,7 @@ pub fn listen(port int) ?Socket { $if debug { println('net.listen($port)') } - s := socket(C.AF_INET, C.SOCK_STREAM, 0) or { + s := new_socket(C.AF_INET, C.SOCK_STREAM, 0) or { return error(err) } bind_res := s.bind(port) or { @@ -167,17 +183,17 @@ pub fn (s Socket) connect(address string, port int) ?int { error_message := os.get_error_msg(net.error_code()) return error('net.connect: getaddrinfo failed "$error_message"') } - res := int(C.connect(s.sockfd, info.ai_addr, info.ai_addrlen)) + res := C.connect(s.sockfd, info.ai_addr, info.ai_addrlen) if res < 0 { error_message := os.get_error_msg(net.error_code()) return error('net.connect: connect failed "$error_message"') } - return int(res) + return res } // helper method to create socket and connect pub fn dial(address string, port int) ?Socket { - s := socket(C.AF_INET, C.SOCK_STREAM, 0) or { + s := new_socket(C.AF_INET, C.SOCK_STREAM, 0) or { return error(err) } res := s.connect(address, port) or { @@ -188,7 +204,7 @@ pub fn dial(address string, port int) ?Socket { // send string data to socket pub fn (s Socket) send(buf byteptr, len int) ?int { - res := int( C.send(s.sockfd, buf, len, MSG_NOSIGNAL) ) + res := C.send(s.sockfd, buf, len, MSG_NOSIGNAL) if res < 0 { return error('net.send: failed with $res') } @@ -198,18 +214,18 @@ pub fn (s Socket) send(buf byteptr, len int) ?int { // receive string data from socket pub fn (s Socket) recv(bufsize int) (byteptr, int) { buf := malloc(bufsize) - res := int( C.recv(s.sockfd, buf, bufsize, 0) ) + res := C.recv(s.sockfd, buf, bufsize, 0) return buf, res } // TODO: remove cread/2 and crecv/2 when the Go net interface is done pub fn (s Socket) cread( buffer byteptr, buffersize int ) int { - return int( C.read(s.sockfd, buffer, buffersize) ) + return C.read(s.sockfd, buffer, buffersize) } // Receive a message from the socket, and place it in a preallocated buffer buf, // with maximum message size bufsize. Returns the length of the received message. pub fn (s Socket) crecv( buffer byteptr, buffersize int ) int { - return int( C.recv(s.sockfd, buffer, buffersize, 0) ) + return C.recv(s.sockfd, buffer, buffersize, 0) } // shutdown and close socket @@ -250,7 +266,7 @@ pub const ( // write - write a string with CRLF after it over the socket s pub fn (s Socket) write(str string) ?int { line := '$str$CRLF' - res := int( C.send(s.sockfd, line.str, line.len, MSG_NOSIGNAL) ) + res := C.send(s.sockfd, line.str, line.len, MSG_NOSIGNAL) if res < 0 { return error('net.write: failed with $res') } return res } @@ -299,6 +315,6 @@ pub fn (s Socket) read_line() string { pub fn (s Socket) get_port() int { mut addr := C.sockaddr_in {} size := 16 // sizeof(sockaddr_in) - sockname_res := C.getsockname(s.sockfd, &addr, &size) - return int(C.ntohs(addr.sin_port)) + C.getsockname(s.sockfd, &addr, &size) + return C.ntohs(addr.sin_port) } diff --git a/vlib/os/os.v b/vlib/os/os.v index 664a7b5e6b..546dd798a5 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -1026,3 +1026,8 @@ pub fn tmpdir() string { } return path } + + +pub fn chmod(path string, mode int) { + C.chmod(path.str, mode) +} diff --git a/vlib/os/os_nix.v b/vlib/os/os_nix.v index 31aab766cd..dac22111d2 100644 --- a/vlib/os/os_nix.v +++ b/vlib/os/os_nix.v @@ -18,11 +18,11 @@ pub fn init_os_args(argc int, argv &byteptr) []string { // get_error_msg return error code representation in string. pub fn get_error_msg(code int) string { - _ptr_text := C.strerror(code) // voidptr? - if _ptr_text == 0 { + ptr_text := C.strerror(code) // voidptr? + if ptr_text == 0 { return '' } - return tos(_ptr_text, vstrlen(_ptr_text)) + return tos3(ptr_text) } pub fn ls(path string) ?[]string { diff --git a/vlib/sqlite/sqlite.v b/vlib/sqlite/sqlite.v index 0d506fb018..131be42a6a 100644 --- a/vlib/sqlite/sqlite.v +++ b/vlib/sqlite/sqlite.v @@ -34,6 +34,11 @@ pub fn (db DB) q_int(query string) int { } fn C.sqlite3_column_text(voidptr, int) byteptr +fn C.sqlite3_column_int(voidptr, int) int +fn C.sqlite3_open() +fn C.sqlite3_step() int +fn C.sqlite3_prepare_v2() +fn C.sqlite3_finalize() pub fn (db DB) q_string(query string) string { stmt := &C.sqlite3_stmt{!} diff --git a/vlib/stbi/stbi.v b/vlib/stbi/stbi.v index 6d5cfc6eb0..0ecddde5d8 100644 --- a/vlib/stbi/stbi.v +++ b/vlib/stbi/stbi.v @@ -21,6 +21,10 @@ mut: ext string } +fn C.stbi_load() voidptr +fn C.stbi_image_free() +fn C.stbi_set_flip_vertically_on_load() + pub fn load(path string) Image { ext := path.all_after('.') mut res := Image { diff --git a/vlib/sync/sync_nix.v b/vlib/sync/sync_nix.v index 2287a81d6d..e00263edc3 100644 --- a/vlib/sync/sync_nix.v +++ b/vlib/sync/sync_nix.v @@ -6,6 +6,11 @@ module sync #include +fn C.pthread_mutex_init() +fn C.pthread_mutex_lock() +fn C.pthread_mutex_unlock() + + //[init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function. pub struct Mutex { mutex C.pthread_mutex_t