Skip to content

Commit 6eeba1b

Browse files
committed
Merge branch 'to-golang' of https://github.com/Samudevv/runic into to-golang
2 parents 8398a0a + 3e9c0a5 commit 6eeba1b

6 files changed

Lines changed: 295 additions & 10 deletions

File tree

‎.gitignore‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ test_data/extern_test_runestone.ini
2828
test_data/extern_test.odin
2929
test_data/wrapper_out*
3030
test_data/test_odin_to_multiple_files*.odin
31-
test_data/to_purego_golang_test*.go
31+
test_data/to_purego_golang_test.go
32+
test_data/to_purego_golang_test-*.go
3233
build/
3334
examples/olivec/olivec/
3435
examples/inih/banini/inih/

‎golang/codegen/purego_to_test.odin‎

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,59 @@ var.windows_globals = Array
168168
err := generate_bindings(rc, rn, RUNE_FILE_NAME, os.to_stream(out_file))
169169
if !testing.expect_value(t, err, nil) do return
170170

171-
data, data_err := os.read_entire_file(
171+
any_data, any_data_err := os.read_entire_file(
172172
"test_data/to_purego_golang_test.go",
173173
context.allocator,
174174
)
175-
if !testing.expect_value(t, data_err, nil) do return
176-
defer delete(data)
175+
if !testing.expect_value(t, any_data_err, nil) do return
176+
defer delete(any_data)
177177

178-
EXPECTED_SOURCE :: `package greatwave
178+
linux_data, linux_data_err := os.read_entire_file(
179+
"test_data/to_purego_golang_test-Linux.go",
180+
context.allocator,
181+
)
182+
if !testing.expect_value(t, linux_data_err, nil) do return
183+
defer delete(linux_data)
179184

180-
func BananaIsMyFan() {
181-
}
182-
`
185+
windows_data, windows_data_err := os.read_entire_file(
186+
"test_data/to_purego_golang_test-Windows.go",
187+
context.allocator,
188+
)
189+
if !testing.expect_value(t, windows_data_err, nil) do return
190+
defer delete(windows_data)
191+
192+
any_exp_data, any_exp_data_err := os.read_entire_file(
193+
"test_data/to_purego_golang_test_expected.go",
194+
context.allocator,
195+
)
196+
if !testing.expect_value(t, any_exp_data_err, nil) do return
197+
defer delete(any_exp_data)
198+
199+
linux_exp_data, linux_exp_data_err := os.read_entire_file(
200+
"test_data/to_purego_golang_test_expected-Linux.go",
201+
context.allocator,
202+
)
203+
if !testing.expect_value(t, linux_exp_data_err, nil) do return
204+
defer delete(linux_exp_data)
183205

184-
diff.expect_diff_strings(t, EXPECTED_SOURCE, string(data))
206+
windows_exp_data, windows_exp_data_err := os.read_entire_file(
207+
"test_data/to_purego_golang_test_expected-Windows.go",
208+
context.allocator,
209+
)
210+
if !testing.expect_value(t, windows_exp_data_err, nil) do return
211+
defer delete(windows_exp_data)
212+
213+
diff.expect_diff_strings(t, string(any_exp_data), string(any_data), ".go")
214+
diff.expect_diff_strings(
215+
t,
216+
string(linux_exp_data),
217+
string(linux_data),
218+
".go",
219+
)
220+
diff.expect_diff_strings(
221+
t,
222+
string(windows_exp_data),
223+
string(windows_data),
224+
".go",
225+
)
185226
}

‎justfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ package ARCH=arch(): release (make-directory BUILD_DIR / 'package')
117117

118118
cp {{ shell("ldd build/runic | grep -v 'linux-vdso\\.\\|libm\\.\\|libc\\.\\|ld-linux-.*\\.' | cut -d' ' -f3 | xargs") }} "{{ BUILD_DIR / 'runic.AppDir' / 'usr' / 'lib' }}"
119119

120-
cd "{{ BUILD_DIR / 'package' }}" && ARCH={{ ARCH }} appimagetool "{{ BUILD_DIR / 'runic.AppDir' }}"
120+
cd "{{ BUILD_DIR / 'package' }}" && ARCH={{ ARCH }} appimagetool '../runic.AppDir'
121121
chmod ugo+x "{{ BUILD_DIR / 'package' / 'runic-' + ARCH + '.AppImage' }}"
122122

123123
rm -r "{{ BUILD_DIR / 'runic.AppDir' }}"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//go:build linux
2+
package greatwave
3+
4+
import (
5+
"unsafe"
6+
)
7+
8+
func LinuxGlobals() Array {
9+
return *(*Array)(unsafe.Pointer(runicPtrLinuxGlobals))
10+
}
11+
12+
func SetLinuxGlobals(value Array) {
13+
*(*Array)(unsafe.Pointer(runicPtrLinuxGlobals)) = value
14+
}
15+
16+
var (
17+
runicPtrLinuxGlobals uintptr
18+
)
19+
20+
var (
21+
runicSymbolsLinux = [][2]any{
22+
{&runicPtrLinuxGlobals, "linux_globals"},
23+
}
24+
25+
runicSymbolsWindows = [][2]any{}
26+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//go:build windows
2+
package greatwave
3+
4+
import (
5+
"unsafe"
6+
)
7+
8+
type Window_Win32 struct {
9+
Name RunicString
10+
Width uint32
11+
Height uint32
12+
Win32id uint
13+
}
14+
15+
var (
16+
CreateWindowWin32 func(NAME string, WIDTH uint32, HEIGHT uint32) *Window_Win32
17+
)
18+
19+
func WindowsGlobals() Array {
20+
return *(*Array)(unsafe.Pointer(runicPtrWindowsGlobals))
21+
}
22+
23+
func SetWindowsGlobals(value Array) {
24+
*(*Array)(unsafe.Pointer(runicPtrWindowsGlobals)) = value
25+
}
26+
27+
var (
28+
runicPtrWindowsGlobals uintptr
29+
)
30+
31+
var (
32+
runicSymbolsWindows = [][2]any{
33+
{&CreateWindowWin32, "create_window_win32"},
34+
{&runicPtrWindowsGlobals, "windows_globals"},
35+
}
36+
37+
runicSymbolsLinux = [][2]any{}
38+
)
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
package greatwave
2+
3+
import (
4+
"errors"
5+
"github.com/ebitengine/purego"
6+
operatingsystem "os"
7+
"runtime"
8+
"unsafe"
9+
)
10+
11+
const (
12+
Max_Array_Size = 4096
13+
Max_Array_Cap = 4096
14+
15+
FruitBanana Fruit = 1
16+
FruitApple Fruit = 2
17+
FruitOrange Fruit = 3
18+
FruitKiwi Fruit = 4
19+
FruitApricot Fruit = 5
20+
FruitPeach Fruit = 6
21+
)
22+
23+
type My_Size_Type uint64
24+
type Window struct {
25+
Name RunicString
26+
Width uint32
27+
Height uint32
28+
}
29+
type Array struct {
30+
Len My_Size_Type
31+
Cap My_Size_Type
32+
Els *uint32
33+
}
34+
type Fruit uint32
35+
36+
var (
37+
CreateWindow func(NAME string, WIDTH uint32, HEIGHT uint32) *Window
38+
GetWindowHandle func(WINDOW *Window) *operatingsystem.Handle
39+
CreateArray func(SIZE My_Size_Type) Array
40+
ArrayAppend func(ARR *Array, VALUE uint32) Array
41+
)
42+
43+
var (
44+
runicSymbols = [][2]any{
45+
{&CreateWindow, "create_window"},
46+
{&GetWindowHandle, "get_window_handle"},
47+
{&CreateArray, "create_array"},
48+
{&ArrayAppend, "array_append"},
49+
}
50+
51+
runicAllSymbols = [][][2]any{
52+
runicSymbols,
53+
runicSymbolsLinux,
54+
runicSymbolsWindows,
55+
}
56+
57+
runicLibraries = map[[2]string]string{
58+
{"linux", "any"}: "libfoo.so",
59+
{"windows", "any"}: "foo.dll",
60+
}
61+
)
62+
63+
64+
/**************************************************************/
65+
/* Public library functions */
66+
/**************************************************************/
67+
68+
// Load the dynamic library and all symbols
69+
func LoadForeignLibrary() error {
70+
for _, runicPlatform := range runicPlatforms {
71+
runicLibraryName, runicLibraryNameOk := runicLibraries[runicPlatform]
72+
if !runicLibraryNameOk {
73+
continue
74+
}
75+
runicLibrary, runicLibraryErr := purego.Dlopen(runicLibraryName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
76+
if runicLibraryErr != nil {
77+
return runicLibraryErr
78+
}
79+
runicForeignLibrary = runicLibrary
80+
}
81+
82+
if runicForeignLibrary == 0 {
83+
return ErrNoLibraryForPlatform
84+
}
85+
86+
for _, runicSomeSymbols := range runicAllSymbols {
87+
if err := runicRegisterSymbols(runicSomeSymbols); err != nil {
88+
return err
89+
}
90+
}
91+
92+
return nil
93+
}
94+
95+
// Unload the library and clean up all resources
96+
func UnloadForeignLibrary() error {
97+
err := purego.Dlclose(runicForeignLibrary)
98+
runicForeignLibrary = 0
99+
return err
100+
}
101+
102+
// Safe. Creates a copy of a C string and returns a go string
103+
func GoString(str RunicString) string {
104+
if str == nil {
105+
return ""
106+
}
107+
108+
var strLen int
109+
ptr := uintptr(unsafe.Pointer(str))
110+
for {
111+
c := *(*uint8)(unsafe.Pointer(ptr))
112+
if c == 0 {
113+
break
114+
}
115+
116+
strLen += 1
117+
ptr += unsafe.Sizeof(*str)
118+
}
119+
120+
slc := unsafe.Slice(str, strLen)
121+
return string(slc)
122+
}
123+
124+
// Unsafe. Only use this function if the underlying C string does not change
125+
func ConstGoString(str RunicString) string {
126+
if str == nil {
127+
return ""
128+
}
129+
130+
var strLen int
131+
ptr := uintptr(unsafe.Pointer(str))
132+
for {
133+
c := *(*uint8)(unsafe.Pointer(ptr))
134+
if c == 0 {
135+
break
136+
}
137+
138+
strLen += 1
139+
ptr += unsafe.Sizeof(*str)
140+
}
141+
142+
return unsafe.String((*byte)(unsafe.Pointer(str)), strLen)
143+
}
144+
145+
/**************************************************************/
146+
/* Internal functions */
147+
/**************************************************************/
148+
149+
type RunicString *uint8
150+
151+
var (
152+
ErrNoLibraryForPlatform = errors.New("Current platform does not have a library")
153+
154+
runicForeignLibrary uintptr
155+
156+
runicPlatforms = [][2]string{
157+
{runtime.GOOS, runtime.GOARCH},
158+
{runtime.GOOS, "any"},
159+
{"any", runtime.GOARCH},
160+
{"any", "any"},
161+
}
162+
)
163+
164+
func runicRegisterSymbols(runicSymbolsParam [][2]any) error {
165+
for _, runicEntry := range runicSymbolsParam {
166+
runicSym, runicSymErr := purego.Dlsym(runicForeignLibrary, runicEntry[1].(string))
167+
if runicSymErr != nil {
168+
return runicSymErr
169+
}
170+
171+
if runicUintptr, runicIsUintptr := runicEntry[0].(*uintptr); runicIsUintptr {
172+
*runicUintptr = runicSym
173+
} else {
174+
purego.RegisterFunc(runicEntry[0], runicSym)
175+
}
176+
}
177+
178+
return nil
179+
}

0 commit comments

Comments
 (0)