Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CStruct with bitfields #43

Open
brentp opened this issue Feb 19, 2023 · 4 comments
Open

CStruct with bitfields #43

brentp opened this issue Feb 19, 2023 · 4 comments

Comments

@brentp
Copy link

brentp commented Feb 19, 2023

Hi, I know it's early days, but I wanted to report this in case there's already a solution. Below is a diff to your examples/{foo.c,ffi.cy} that shows the issue. In short, how to handle C structs that use bit fields?

diff --git a/examples/ffi.cy b/examples/ffi.cy
index 0d8aedf..4f03827 100644
--- a/examples/ffi.cy
+++ b/examples/ffi.cy
@@ -7,7 +7,18 @@
 
 import os 'os'
 
+object bitStruct:
+  flag uint32
+  other uint32
+
+
 lib = os.bindLib('./libfoo.so', [
     os.CFunc{ sym: 'add', args: [#int, #int], ret: #int }
+    os.CFunc{ sym: 'getBitStruct', args: [#uint], ret: bitStruct }
+    os.CStruct{ fields: [#uint, #uint], type: bitStruct}
 ])
-lib.add(123, 321)
+print lib.add(123, 321)
+
+
+print lib.getBitStruct(22).flag
+
diff --git a/examples/foo.c b/examples/foo.c
index 082fc1e..22909ff 100644
--- a/examples/foo.c
+++ b/examples/foo.c
@@ -1,3 +1,16 @@
+#include <stdint.h>
+
+typedef struct bitStruct {
+    uint32_t flag: 1, other: 31;
+} bitStruct;
+
+bitStruct getBitStruct(uint32_t a) {
+   bitStruct b;
+   b.flag = 1;
+   b.other = a;
+   return b;
+}
+
 int add(int a, int b) {
     return a + b;
-}
\ No newline at end of file
+}
@fubark
Copy link
Owner

fubark commented Feb 20, 2023

This hasn't been implemented yet but I did check that it's possible with libtcc. It would look something like this in Cyber:

import os 'os'

lib = os.bindLib('./libfoo.so', [
    os.CFunc{ sym: 'getBitStruct', args: [#uint], ret: bitStruct }
    os.CStruct{ fields: [os.CuintBits(1), os.CuintBits(31)], type: bitStruct }
])

object bitStruct:
  flag number
  other number

s = lib.getBitStruct(22)
print s.flag
print s.other

@brentp
Copy link
Author

brentp commented Feb 20, 2023

I see. Thanks for the response.
For that example, I also don't mind bitshifting myself. I do have a related question. I was just trying out wrapping htslib. The first function is hts_open with this signature:

htsFile *hts_open(const char *fn, const char *mode);

where htsFile is:

typedef struct htsFile {
    uint32_t is_bin:1, is_write:1, is_be:1, is_cram:1, is_bgzf:1, dummy:27;
    int64_t lineno;
    kstring_t line;
    char *fn, *fn_aux;
    union {
        BGZF *bgzf;
        struct cram_fd *cram;
        struct hFILE *hfile;
    } fp;
    void *state;  // format specific state information
    htsFormat format;
    hts_idx_t *idx;
    const char *fnidx;
    struct sam_hdr_t *bam_header;
    struct hts_filter_t *filter;
} htsFile;

so I'd prefer not to specify that in cyber. In fact it can be completely opaque.
I tried this:

import os 'os'

hts = os.bindLib('libhts.so', [
    os.CFunc{ sym: 'hts_open', args: [#charPtrZ, #charPtrZ], ret: #ptr}
])
print hts

h = hts.hts_open("../htslib/test/range.bam")
print h

but I see:

BindLib53175d61490b23df
panic: Missing method symbol `hts_open` from receiver of type `BindLib53175d61490b23df`.

/home/brentp/src/cyber/bam.cy:8:5 main:
h = hts.hts_open("../htslib/test/range.bam")
    ^

Is there a way to do this without writing a separate shared lib containing a wrapper function that returns a void *?

@fubark
Copy link
Owner

fubark commented Feb 20, 2023

You've set up bindLib correctly, but you called hts_open with 1 arg instead of 2. Since Cyber currently has function overloading by number of params, it say's it's missing a symbol. I'll make the error message more descriptive.

Is there a way to do this without writing a separate shared lib containing a wrapper function that returns a void *

That's the intended purpose of #ptr, I think it will be renamed to #voidPtr in the near future.

@brentp
Copy link
Author

brentp commented Feb 20, 2023

You've set up bindLib correctly, but you called hts_open with 1 arg instead of 2. Since Cyber currently has function overloading by number of params, it say's it's missing a symbol. I'll make the error message more descriptive.

Oh, wow. Thanks for noticing this. Indeed it's working now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants