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

Zig Support #2471

Closed
kassane opened this issue Jan 3, 2023 · 8 comments
Closed

Zig Support #2471

kassane opened this issue Jan 3, 2023 · 8 comments

Comments

@kassane
Copy link

kassane commented Jan 3, 2023

HomePage: https://ziglang.org

Zig and its easy interoperability with C(89). However there is no indication of supporting C++ directly.

I experimented with SWIG 4.x today and used the example of exporting List<T> to Go and took advantage of the conversion and ported it to Zig and used built-in header declaration in Go (example) in example.h file and also used zig translate-c convert C to Zig (although it is not demanding when I can just use @cImport(@cInclude("example.h"));).

And it worked normally! However SWIG does not target the C++ to C language.

C++ - List impl
%module example
%{
#include "source.h"
%}

%include "source.h"
%template(intList) List<int>;
%template(doubleList) List<double>;
template <class T> class List {
private:
  T *data;
  int nitems;
  int maxitems;

public:
  List(int max) {
    data = new T[max];
    nitems = 0;
    maxitems = max;
  }
  ~List() { delete[] data; };
  void append(T obj) {
    if (nitems < maxitems) {
      data[nitems++] = obj;
    }
  }
  int length() { return nitems; }
  T get(int n) { return data[n]; }
};
Zig - preview code

Cleaned code (refactored):

pub const swig_intgo = c_longlong;
pub const uintgo = c_ulonglong;
pub const _gostring_ = extern struct {
    p: [*c]u8,
    n: swig_intgo,
};
pub const _goslice_ = extern struct {
    array: ?*anyopaque,
    len: swig_intgo,
    cap: swig_intgo,
};
pub extern fn _wrap_Swig_free_example_0724c017468ff621(arg1: usize) void;
pub extern fn _wrap_Swig_malloc_example_0724c017468ff621(arg1: swig_intgo) usize;
pub extern fn _wrap_new_intList_example_0724c017468ff621(arg1: swig_intgo) usize;
pub extern fn _wrap_delete_intList_example_0724c017468ff621(arg1: usize) void;
pub extern fn _wrap_intList_append_example_0724c017468ff621(arg1: usize, arg2: swig_intgo) void;
pub extern fn _wrap_intList_length_example_0724c017468ff621(arg1: usize) swig_intgo;
pub extern fn _wrap_intList_get_example_0724c017468ff621(arg1: usize, arg2: swig_intgo) swig_intgo;
pub extern fn _wrap_new_doubleList_example_0724c017468ff621(arg1: swig_intgo) usize;
pub extern fn _wrap_delete_doubleList_example_0724c017468ff621(arg1: usize) void;
pub extern fn _wrap_doubleList_append_example_0724c017468ff621(arg1: usize, arg2: f64) void;
pub extern fn _wrap_doubleList_length_example_0724c017468ff621(arg1: usize) swig_intgo;
pub extern fn _wrap_doubleList_get_example_0724c017468ff621(arg1: usize, arg2: swig_intgo) f64;

pub const SwigcptrDoubleList = extern struct {
    const Self = @This();
    pub fn New(self: *Self, value: swig_intgo) void {
        self.value = _wrap_new_doubleList_example_0724c017468ff621(value);
    }
    pub fn Append(self: *Self, arg2: f64) void {
        _wrap_doubleList_append_example_0724c017468ff621(self.value, arg2);
    }
    pub fn Length(self: *Self) swig_intgo {
        return _wrap_doubleList_length_example_0724c017468ff621(self.value);
    }
    pub fn Get(self: *Self, arg2: swig_intgo) f64 {
        return _wrap_doubleList_get_example_0724c017468ff621(self.value, arg2);
    }

    value: usize,
};
pub const DoubleList = extern struct {
    SwigDoubleList: SwigcptrDoubleList,
};

pub fn main() void {
    const print = @import("std").debug.print;
    var list: DoubleList = undefined;
    list.SwigDoubleList.New(@as(swig_intgo, 5));
    list.SwigDoubleList.Append(4.3);
    list.SwigDoubleList.Append(5.6);
    list.SwigDoubleList.Append(1.6);
    print("List size: {d}\n", .{list.SwigDoubleList.Length()});
    print("Get value: {d}\n", .{list.SwigDoubleList.Get(@as(swig_intgo, 1))});
}

Would it be helpful to have if not another programming language as zig in the list like every other language, or to just have the C language on the target too?

@vadz
Copy link
Member

vadz commented Jan 3, 2023

However SWIG does not target the C++ to C language.

See #2086.

@kassane
Copy link
Author

kassane commented Jan 3, 2023

However SWIG does not target the C++ to C language.

See #2086.

Wow! Interesting hope it gets merged. This would lessen the high demands of immediately attaching new languages ​​to the project.

I've been reading the manual for this fork, seems to meet the trivial requirements.
https://htmlpreview.github.io/?https://github.com/vadz/swig/blob/C/Doc/Manual/C.html


Edit

Reading PR comments one can see some impediments about the fork. 😕

@kassane
Copy link
Author

kassane commented Jan 4, 2023

Nice, building the latest version of SWIG with Zig (cc/c++ [clang wrapper]), probably helps with cross-compiling.

$> ~/Swig/bin/swig -version

SWIG Version 4.2.0

Compiled with zig c++ -fno-sanitize=all -target x86_64-linux-musl -lc++  [x86_64-pc-linux-musl]

Configured options: -pcre

Please see https://www.swig.org for reporting bugs and further information

@kassane
Copy link
Author

kassane commented Jan 6, 2023

Is it possible for Swig to generate C header instead of putting declarations in Go directly? @ojwb

@ojwb
Copy link
Member

ojwb commented Jan 7, 2023

Not sure why you're asking me that, but anyway, that's already been answered above - that's what the C target language in #2086 does.

The conclusion here seems to be that Zig can wrap a C API automatically so having a full Zig target language isn't worth the time and effort to implement and maintain - better to put that effort into actually getting the C target language merged. Hence closing.

@ojwb ojwb closed this as completed Jan 7, 2023
@kassane
Copy link
Author

kassane commented Jan 8, 2023

Not sure why you're asking me that, but anyway, that's already been answered above

Yes, it might not be worth adding another language to the list like so many others.

I asked him because of his feedback regarding golang support in Swig.

I believe it would be interesting for the
Go(cgo) code to be provided with a C header instead of simply placing it in the Go file.
I don't know how much it would impact the PR C Backend, realized that in the Go target commands, it is not possible to simply separate the already translated statements. If it were possible, it would greatly reduce the need to formulate a new backend.

@wsfulton
Copy link
Member

wsfulton commented Jan 8, 2023

@kassane, I would avoid using the SWIG Go module as a basis for any other language like Zig, or use it for any purpose other than for only Go wrappers. This is because the Go module is fundamentally flawed and when fixed is likely to change quite a lot and quite possibly in a non-backwards compatible manner, see #2337.

If the C language module was designed for use as a basis for other target languages, then you could build Zig wrappers on top of it. But it isn't. It's actually quite unclear what the design goals of it are as it is currently poorly documented. Nevertheless, the standard approach to writing new SWIG language modules is to take another existing similar (mature) language module and tweak it for the new target language and this is what I suggest is still done for any new language.

@ojwb
Copy link
Member

ojwb commented Jan 8, 2023

@wsfulton I don't think the idea here is about building a new SWIG target language on the C target language (at least that's not what I was talking about).

AIUI, Zig can automatically wrap a C API but not a C++ API. With a SWIG C target language one could wrap a C++ API to a C one, then point Zig at that C API to allow using a C++ library from Zig.

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

4 participants