hashlink icon indicating copy to clipboard operation
hashlink copied to clipboard

libuv 1.42 bindings

Open RealyUniqueName opened this issue 4 years ago • 8 comments

See HaxeFoundation/haxe#10342

I'm unexpirienced with C/C++. Especially with memory management. Please, review thoroughly.

Questions to figure out:

  • [ ] - ~how to construct and throw instances of hl.uv.UVException~ (see https://github.com/HaxeFoundation/hashlink/pull/464#issuecomment-899044606)
  • [ ] - ~how to construct Haxe's strings and arrays from C without the need for wrapping code on Haxe side.~ (see https://github.com/HaxeFoundation/hashlink/pull/464#issuecomment-899044606)
  • [ ] - hashlink has no type for uint64_t. Currently all occurences of uint64_t are mapped to int64
  • [ ] - I64 is not fully supported (e.g. haxe code i64_a == i64_b produces jit error)
  • [ ] - ~how to provide defined constant values for Haxe code (e.g. how to make values of enum abstract UVError(Int) to be the same as corresponding UV_E* constants)~ (see https://github.com/HaxeFoundation/hashlink/pull/464#issuecomment-899044606)

RealyUniqueName avatar Aug 04 '21 17:08 RealyUniqueName

as a workaround for u/i64 troubles in my bgfx bindings (not public) I had to use haxe.Int64 and pass the high/low as separate i32's that get combined again by a macro. it's ugly but it works.

for the enum abstract UVError(Int) issue you might be looking for enum abstract UVError(Int) from Int to Int (but I might misunderstand the issue? I've forgotten about this being available a few times I've needed it)

and for strings and arrays I've had to wrap them in the haxe bindings too - not aware of any other way.

shakesoda avatar Aug 04 '21 18:08 shakesoda

how to construct and throw instances of hl.uv.UVException

You don't. Usually you would return error code / false / null and throw the appropriate error in the wrapper.

how to construct Haxe's strings and arrays from C without the need for wrapping code on Haxe side.

You don't. This is the job of the wrapper to do the Haxe wrapping. Usually you expose the C functions almost "as-it" with little or no change vs their C declaration. Then all the wrapping and extra logic is done on Haxe side. This allows a more flexible approach as you can use the whole API directly and the Haxe code is more expressive than C / less error prone.

hashlink has no type for uint64_t. Currently all occurences of uint64_t are mapped to int64 I64 is not fully supported (e.g. haxe code i64_a == i64_b produces jit error)

You can use hl.I64 , see discussion wrt I64 implementation

how to provide defined constant values for Haxe code (e.g. how to make values of enum abstract UVError(Int) to be the same as corresponding UV_E* constants)

This requires to copy / paste the values from C headers to Haxe headers. These values are very rarely changed in C implementation, I haven't had a case that was changing them depending on library version.

ncannasse avatar Aug 15 '21 12:08 ncannasse

I get some "char *" values from libuv. And I want to use them as hl's bytes as-is. Do I need to register them in the GC somehow? @ncannasse ?

RealyUniqueName avatar Aug 25 '21 13:08 RealyUniqueName

@RealyUniqueName no it's fine, you can access any C data structure or bytes directly from HL without any wrapper. GC cooperation is only required if the C side can free() the data and then you might access this memory which is not good.

ncannasse avatar Aug 25 '21 13:08 ncannasse

@ncannasse and if it's not free'd on C side, will GC automatically free it after I don't reference it from Haxe code?

RealyUniqueName avatar Aug 25 '21 13:08 RealyUniqueName

No the GC can only free the pointers it allocates.

Le mer. 25 août 2021 à 15:30, Aleksandr Kuzmenko @.***> a écrit :

@ncannasse https://github.com/ncannasse and if it's not free'd on C side, will GC automatically free it after I don't reference it from Haxe code?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/HaxeFoundation/hashlink/pull/464#issuecomment-905503076, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHZXQCXB5D3NE6JE2LIZUTT6TV5RANCNFSM5BRUY6NQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email .

ncannasse avatar Aug 25 '21 18:08 ncannasse

@ncannasse this one is ready for review. If you're using github interface you can jump right to uv.c file as everything prior to this file is just a libuv 1.9->1.42 update.

OSX ci failures are not related to this PR.

RealyUniqueName avatar Sep 06 '21 20:09 RealyUniqueName

how to provide defined constant values for Haxe code (e.g. how to make values of enum abstract UVError(Int) to be the same as corresponding UV_E* constants)

This requires to copy / paste the values from C headers to Haxe headers. These values are very rarely changed in C implementation, I haven't had a case that was changing them depending on library version.

Something to point out here is that it's not so much about the values changing, the real problem is that these values may vary depending on the OS. See http://docs.libuv.org/en/v1.x/errors.html:

Note Implementation detail: on Unix error codes are the negated errno (or -errno), while on Windows they are defined by libuv to arbitrary negative numbers.

In the old asys implementation for eval we had this on the C-side:

CAMLprim value hx_get_errno(value unit) {
	CAMLparam1(unit);
	const char* names[] = {"E2BIG", "EACCES", "EADDRINUSE", "EADDRNOTAVAIL", "EAFNOSUPPORT", "EAGAIN", "EAI_ADDRFAMILY", "EAI_AGAIN", "EAI_BADFLAGS", "EAI_BADHINTS", "EAI_CANCELED", "EAI_FAIL", "EAI_FAMILY", "EAI_MEMORY", "EAI_NODATA", "EAI_NONAME", "EAI_OVERFLOW", "EAI_PROTOCOL", "EAI_SERVICE", "EAI_SOCKTYPE", "EALREADY", "EBADF", "EBUSY", "ECANCELED", "ECHARSET", "ECONNABORTED", "ECONNREFUSED", "ECONNRESET", "EDESTADDRREQ", "EEXIST", "EFAULT", "EFBIG", "EHOSTUNREACH", "EINTR", "EINVAL", "EIO", "EISCONN", "EISDIR", "ELOOP", "EMFILE", "EMSGSIZE", "ENAMETOOLONG", "ENETDOWN", "ENETUNREACH", "ENFILE", "ENOBUFS", "ENODEV", "ENOENT", "ENOMEM", "ENONET", "ENOPROTOOPT", "ENOSPC", "ENOSYS", "ENOTCONN", "ENOTDIR", "ENOTEMPTY", "ENOTSOCK", "ENOTSUP", "EPERM", "EPIPE", "EPROTO", "EPROTONOSUPPORT", "EPROTOTYPE", "ERANGE", "EROFS", "ESHUTDOWN", "ESPIPE", "ESRCH", "ETIMEDOUT", "ETXTBSY", "EXDEV", "UNKNOWN", "EOF", "ENXIO", "EMLINK", "EHOSTDOWN", "EOTHER"};
	int values[] = {UV_E2BIG, UV_EACCES, UV_EADDRINUSE, UV_EADDRNOTAVAIL, UV_EAFNOSUPPORT, UV_EAGAIN, UV_EAI_ADDRFAMILY, UV_EAI_AGAIN, UV_EAI_BADFLAGS, UV_EAI_BADHINTS, UV_EAI_CANCELED, UV_EAI_FAIL, UV_EAI_FAMILY, UV_EAI_MEMORY, UV_EAI_NODATA, UV_EAI_NONAME, UV_EAI_OVERFLOW, UV_EAI_PROTOCOL, UV_EAI_SERVICE, UV_EAI_SOCKTYPE, UV_EALREADY, UV_EBADF, UV_EBUSY, UV_ECANCELED, UV_ECHARSET, UV_ECONNABORTED, UV_ECONNREFUSED, UV_ECONNRESET, UV_EDESTADDRREQ, UV_EEXIST, UV_EFAULT, UV_EFBIG, UV_EHOSTUNREACH, UV_EINTR, UV_EINVAL, UV_EIO, UV_EISCONN, UV_EISDIR, UV_ELOOP, UV_EMFILE, UV_EMSGSIZE, UV_ENAMETOOLONG, UV_ENETDOWN, UV_ENETUNREACH, UV_ENFILE, UV_ENOBUFS, UV_ENODEV, UV_ENOENT, UV_ENOMEM, UV_ENONET, UV_ENOPROTOOPT, UV_ENOSPC, UV_ENOSYS, UV_ENOTCONN, UV_ENOTDIR, UV_ENOTEMPTY, UV_ENOTSOCK, UV_ENOTSUP, UV_EPERM, UV_EPIPE, UV_EPROTO, UV_EPROTONOSUPPORT, UV_EPROTOTYPE, UV_ERANGE, UV_EROFS, UV_ESHUTDOWN, UV_ESPIPE, UV_ESRCH, UV_ETIMEDOUT, UV_ETXTBSY, UV_EXDEV, UV_UNKNOWN, UV_EOF, UV_ENXIO, UV_EMLINK, UV_EHOSTDOWN, 0};
	CAMLreturn(build_fields(sizeof(values) / sizeof(values[0]), names, values));
}

This would then get assigned in a way that would match the native representation of an extern enum abstract UVErrorType(Int).

This should be possible for HL as well.

Simn avatar Apr 11 '22 10:04 Simn