How to use Scala Native to represent union in C

Hi there,
Recently I am exploring the usage of Scala Native. I have a third party C library, and I hope to call it in Scala using Scala Native.
There is a struct with a filed of union type, I wonder how can I use Scala native to express it?

type struct bwTRreeNode_t {
      unit8_t a;
}

type struct bwTRee {
   uint8_t isLeaft;
   union {
       uint64_t * size;
       struct bwTReeNode_t ** child;
   } x;
};

From the link Native code interoperability — Scala Native 0.5.6 documentation, I know we can use

import scala.scalanative.unsafe._

@extern
object libc {
  // pointer to bwTReeNode_t in C
  type bwTRreeNode_t = Ptr[CStruct1[CUnsignedShort]]]
  type bwTRee_t = Ptr[CStruct2[CUnsignedShort, 
                               ??Union2[CUnsignedLong, Ptr[bwTRreeNode_t]]]]
}

I can represent the struct, but not sure how to express the union inside the struct. Anyone has suggestions? Really appreciate it!

Thanks!
Songpeng

1 Like

Hey @beyondpie

I’m facing a very similar case. And google leads me here, but nobody show their answers yet.

And later I may make an MVP example. I’m trying to write bindings for libcurl and there is

struct CURLMsg {
  CURLMSG msg;       /* what this message means */
  CURL *easy_handle; /* the handle it concerns */
  union {
    void *whatever;    /* message-specific data */
    CURLcode result;   /* return code for transfer */
  } data;
};
typedef struct CURLMsg CURLMsg;

The data field is a union type in Clang. And my Scala Native binding is looking like this:

  type CurlMsgData = CVoidPtr | CurlCode
  object CurlMsgData:
    /**
     * its size must be the max of the two sizes, its alignment the max of the two alignments
     */
    given tagCurlMsgData: Tag[CurlMsgData] = {
      val tagPtr = summon[Tag[CVoidPtr]]
      val tagCode = summon[Tag[CurlCode]]


      if tagPtr.size >= tagCode.size
      then tagPtr.asInstanceOf[Tag[CurlMsgData]]
      else tagCode.asInstanceOf[Tag[CurlMsgData]]
    }

You could find more in here lqhuang/scala-native-http/…/libcurl/multi.scala#L128-L140

Basically, Tag[T] helps to compiler to know how large memory it should allocate, in my case I will allocate the data field with the larger one memory between two union types.

Compiling is successful :), but I haven’t do full tests for all features yet. Just FYI.

Welcome to discuss!

Regards
Lanqing

4 Likes

You probably want to use sn-bindgen instead of writing bindings by hand. Here are the docs

The author is often on Scala Discord it’s best to ask more there. (Google won’t have much info)

1 Like

@spamegg1 Thanks for reply!

I have lots of inspirations from your talk (Scala Native system programming) on YouTube!

In fact, I did this on purpose. What’s more, I also try to follow the similar module structure as the original curl library and intentionally keep almost the same order of the symbols first defined in the header files.

I hope I could maintain it as long as curl evolution. Hence, I may easily follow what changed in the upstream by this approach.

Anton Sviridov recommended handcrafted bindings in this comment https://github.com/com-lihaoyi/requests-scala/issues/156#issuecomment-2172928437, too.

On the other hand, this is my first time writing bindings for C libraries. This medium-sized project is a good opportunity for me to compare the differences between manually written code and generated code. Indeed, I’ve found some potential improvements, which I will try to feed back to upstream later.

It’s quite a coincidence, as I was planning to invite you to do some code reviews before the first RC release to Maven Central in the future.

I’m really appreciate your advises :smile: If you have more interest in this, feel free to check my development logs here

Cheers!

1 Like

That wasn’t me, maybe you are thinking of Wojciech Mazur?

Oh OK :sweat_smile: if he says so…

It’s great if you can do that. But maintenance is always a burden, so think ahead first.

Again I think you confused me with someone else :laughing:

Oh, no. Sorry for that.

Because you have a repo about https://github.com/spamegg1/modern-systems-scala-native

And you often appeared in my timeline (I followed you on GitHub). I misrecognize you as Richard Whaling. :melting_face: :smiling_face_with_tear:

I watched his talk about Fast, Simple Concurrency with Scala Native. There are some examples for curl and libuv.

Wojciech Mazur is also a great presenter.

Anyway, thanks for your feedbacks, too! I learned from you already!

Regards.

1 Like

@lqhuang @spamegg1
Thank you, guys! I thought no one will respond to it because maybe no one use Scala Native any more?
I also submitted an issue on Github: How to use Scala Native to represent union in C · Issue #4339 · scala-native/scala-native · GitHub. They nicely gave me lots of suggestions. But I haven’t give them a hard try yet.
Your answers encourage me to keep following Scala Native.
Songpeng

1 Like