NSDictionary and golang strings issue
Closed this issue · 8 comments
package main
import "github.com/progrium/macdriver/core"
import "fmt"
func main() {
dict := core.NSDictionary_Init("one", "two")
fmt.Println("dictionary:", dict)
}
This program adds golang strings to an NSDictionary. When the program is ran it panics with this message:
2023/07/02 00:20:26 unhandled kind: string
panic: unhandled kind: string
goroutine 1 [running]:
log.Panicf({0x1004c14a8?, 0x1004ed2c0?}, {0x140000abe30?, 0x140000b4010?, 0x100918d28?})
/usr/local/go/src/log/log.go:391 +0x64
github.com/progrium/macdriver/objc.sendMsg({0x1005044e8, 0x140000b4020}, 0x0, {0x1004c2495, 0x17}, {0x140000c0000, 0x2, 0x1004b3f38?})
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/objc/msg_arm64.go:159 +0xf28
github.com/progrium/macdriver/objc.object.Send(...)
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/objc/msg_arm64.go:206
github.com/progrium/macdriver/core.NSDictionary_Init({0x140000c0000, 0x2, 0x2})
/Users/user/go/pkg/mod/github.com/progrium/macdriver@v0.3.0/core/NSDictionary.go:17 +0x50
main.main()
/Users/user/desktop/my go app/main.go:7 +0x58
exit status 2
Could a feature be added that makes golang strings usable in an NSDictionary?
All strings need to ultimately be wrapped with core.String()
, so that should help here. I think the idea was the manual bindings would do this for you, but when it takes arguments of any type here we can't do that. Well, we could have a function do a type switch and convert...
Ok I tried wrapping the strings but I still see an error. Here is the program I made:
package main
import "github.com/progrium/macdriver/core"
import "fmt"
func main() {
oneStr := core.String("one")
twoStr := core.String("two")
dict := core.NSDictionary_Init(oneStr, twoStr, nil)
fmt.Println("dictionary:", dict)
}
When I run it I see this error:
2023-07-02 08:05:48.788 main[1459:20783] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSPlaceholderDictionary initWithObjectsAndKeys:]: second object of each pair must be non-nil. Or, did you forget to nil-terminate your parameter list?'
*** First throw call stack:
(
0 CoreFoundation 0x00000001bf532b08 __exceptionPreprocess + 240
1 libobjc.A.dylib 0x00000001bf27de14 objc_exception_throw + 60
2 CoreFoundation 0x00000001bf476764 -[NSDictionary initWithObjectsAndKeys:] + 792
3 main 0x0000000104a16960 VariadicCall + 96
4 ??? 0x000001400011c750 0x0 + 1374390699856
)
libc++abi: terminating with uncaught exception of type NSException
SIGABRT: abort
PC=0x1bf3b0db8 m=0 sigcode=0
signal arrived during cgo execution
Did I do something wrong?
Hmm... not sure it's you. Could be related to not supporting Golang nil. Could be related to variadic calls. Also raises the issue that at least the core/foundation code should probably have some tests.
Can you try the equivalent of this using darwinkit
or in main
when this PR is merged:
#176
Well I did try to but I ran into a few problem. There are no NSDictionary Init() or dictionaryWithObjectsAndKeys() methods. Not sure how to create an NSDictionary object.
https://pkg.go.dev/github.com/progrium/macdriver@v0.4.1-0.20230817085234-363adeff1ee6/macos/foundation#NewDictionary
https://pkg.go.dev/github.com/progrium/macdriver@v0.4.1-0.20230817085234-363adeff1ee6/macos/foundation#Dictionary_DictionaryWithObjectsAndKeys
But it looks like we don't support variadic methods! Making a separate issue: #181
It should work with the latest PR, though the first object still has to be an IObject
, however there are some custom helpers for more easily building NSDictionaries from Go maps. There is now a test case that demonstrates all of this, which I'll include here:
func TestFoundationDictionary(t *testing.T) {
s := String_StringWithString("bar")
d1 := Dictionary_DictionaryWithObjectsAndKeys(s, "foo", "value", "key", nil)
m1 := DictToMap[string, string](d1)
d2 := DictOf(m1)
m2 := DictToMap[string, string](d2)
if !reflect.DeepEqual(m2, map[string]string{
"foo": "bar",
"key": "value",
}) {
t.Fatal("unexpected final map from dictionary")
}
}
Closing since there are tests passing that satisfy the original issue. Please open another issue or discussion if there is still a problem or question.