go x/mobile: 在Swift中导出的structs无法保留字段值

yqkkidmi  于 5个月前  发布在  Go
关注(0)|答案(6)|浏览(58)

你正在使用哪个版本的Go( go version )?

$ go version go1.12.4 darwin/amd64

这个问题在最新版本中是否重现?

还没有测试过

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GOARCH="amd64"
GOBIN="/Users/tristian/go/bin"
GOCACHE="/Users/tristian/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/tristian/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/Cellar/go/1.12.4/libexec"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.12.4/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/g1/v3hz1sm92nv7wbzpg3dx_h_h0000gp/T/go-build064001605=/tmp/go-build -gno-record-gcc-switches -fno-common"

你做了什么?

我正在使用最新的 gomobile ,从这个提交安装:

commit 32b2708ab17190067486adc3513cae8dc2a7e5a4 (HEAD -> master, origin/master, origin/HEAD)
Author: Mark Villacampa <m@markvillacampa.com>
Date:   Thu May 9 10:20:13 2019 +0000

在我使用的go源代码中,我添加了一个作为Gomobile一部分公开的结构体类型。

type Config struct {
  OSName string
  OSDevice string
}

// NewConfig()
func NewConfig() *Config { 
  return &Config{}
}

在Swift代码中,我使用以下方式创建一个示例并设置一些字段。

// "Mobile" is the prefix package name
// var config = MobileNewConfig() (tried this too)
let config = MobileNewConfig()

config?.osName = "some name"
config?.osDevice = "some string"

我像这样构建框架:

GO111MODULE=off gomobile bind -a -v -target=ios/arm,ios/arm64,ios/amd64 example.com/mobile

你期望看到什么?

我期望看到 config 变量在swift代码中保留分配的字符串值。

你看到了什么?

相反, config 变量没有保留swift值,例如,请查看此调试器捕获:

klh5stk1

klh5stk11#

我已经创建了以下仓库来重现这个问题:

xjreopfe

xjreopfe2#

我认为我已经找到了问题,基本上当我们使用以下命令将框架绑定时:

gomobile bind -v -target=ios -work .

如果我们 cd 进入生成的objc文件,我们可以看到以下内容在 src/gobind/Mobile_darwin.m

- (NSString* _Nonnull)osName {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring r0 = proxymobile_Config_OSName_Get(refnum);
	NSString *_r0 = go_seq_to_objc_string(r0);
	return _r0;
}

- (void)setOSName:(NSString* _Nonnull)v {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring _v = go_seq_from_objc_string(v);
	proxymobile_Config_OSName_Set(refnum, _v);
}

然而,Label 属性访问器看起来像这样:

- (NSString* _Nonnull)label {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring r0 = proxymobile_Config_Label_Get(refnum);
	NSString *_r0 = go_seq_to_objc_string(r0);
	return _r0;
}

- (void)setLabel:(NSString* _Nonnull)v {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring _v = go_seq_from_objc_string(v);
	proxymobile_Config_Label_Set(refnum, _v);
}
kq4fsx7k

kq4fsx7k3#

我已经更新了重现此问题的仓库:

如果将以下补丁应用到 gomobile :
golang/mobile@master...triztian:issue/32008
那么我们重新初始化:gomobile init ,然后最后在重现问题中重新运行以下内容:

make clean run

可执行文件表现得像预期的那样,即我得到以下结果:

λ ~/go/src/github.com/triztian/gomobileprops (master): make clean run
rm -rf Mobile.framework main
gomobilex bind -v -target=ios -work .
WORK=/var/folders/g1/v3hz1sm92nv7wbzpg3dx_h_h0000gp/T/gomobile-work-227841999/go-build475590256
runtime/cgo
golang.org/x/mobile/internal/mobileinit
gobind
WORK=/var/folders/g1/v3hz1sm92nv7wbzpg3dx_h_h0000gp/T/gomobile-work-227841999/go-build084453767
runtime/cgo
golang.org/x/mobile/internal/mobileinit
gobind
WORK=/var/folders/g1/v3hz1sm92nv7wbzpg3dx_h_h0000gp/T/gomobile-work-227841999/go-build110091045
runtime/cgo
golang.org/x/mobile/internal/mobileinit
gobind
WORK=/var/folders/g1/v3hz1sm92nv7wbzpg3dx_h_h0000gp/T/gomobile-work-227841999/go-build083494747
runtime/cgo
golang.org/x/mobile/internal/mobileinit
gobind
write Mobile.framework/Versions/A/Headers/Mobile.objc.h
write Mobile.framework/Versions/A/Headers/Universe.objc.h
write Mobile.framework/Versions/A/Headers/ref.h
write Mobile.framework/Versions/A/Headers/Mobile.h
write Mobile.framework/Resources/Info.plist
write Mobile.framework/Versions/A/Modules/module.modulemap
WORK=/var/folders/g1/v3hz1sm92nv7wbzpg3dx_h_h0000gp/T/gomobile-work-227841999
swiftc -g -F. main.swift
<module-includes>:2:9: note: in file included from <module-includes>:2:
#import "Headers/Mobile.objc.h"
        ^
/Users/tristian/go/src/github.com/triztian/gomobileprops/./Mobile.framework/Headers/Mobile.objc.h:21:1: warning: conflicting nullability specifier on return types, 'nullable' conflicts with existing specifier 'nonnull'
- (nullable instancetype)init;
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/objc/NSObject.h:63:1: note: previous declaration is here
- (instancetype)init
^
./main
Success osName: THE OSNAME

应用补丁后生成的 访问器 如下:

- (NSString* _Nonnull)label {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring r0 = proxymobile_Config_Label_Get(refnum);
	NSString *_r0 = go_seq_to_objc_string(r0);
	return _r0;
}

- (void)setLabel:(NSString* _Nonnull)v {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring _v = go_seq_from_objc_string(v);
	proxymobile_Config_Label_Set(refnum, _v);
}

- (NSString* _Nonnull)osName {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring r0 = proxymobile_Config_OSName_Get(refnum);
	NSString *_r0 = go_seq_to_objc_string(r0);
	return _r0;
}

- (void)setOsName:(NSString* _Nonnull)v {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring _v = go_seq_from_objc_string(v);
	proxymobile_Config_OSName_Set(refnum, _v);
}

我会创建一个 PR ,但是如果我运行 go test ./bind 命令,许多测试针对 golden 文件都会失败,例如 ./bind/testdata/doc.objc.m.golden 对于名为 sf 的字段期望以下内容:

- (NSString* _Nonnull)sf {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring r0 = proxydoc_S_SF_Get(refnum);
	NSString *_r0 = go_seq_to_objc_string(r0);
	return _r0;
}

- (void)setSF:(NSString* _Nonnull)v {
	int32_t refnum = go_seq_go_to_refnum(self._ref);
	nstring _v = go_seq_from_objc_string(v);
	proxydoc_S_SF_Set(refnum, _v);
}

我在此处找到了大小写规则:

@eliasnaur 我应该采取什么措施来创建一个可接受的 PR ?是否有特定的过程来更新黄金文件?
我认为这会影响遵循首字母缩略词命名规范的任何人,并且这是一个静默显现的问题。

jfgube3f

jfgube3f4#

你可以使用以下命令更新golden文件:

go test ./bind -update
23c0lvtd

23c0lvtd5#

感谢您的快速回复,我已经完成了这个操作,似乎已经修复了测试:

λ ~/go/src/golang.org/x/mobile (issue/32008b): go test ./bind/ -update
ok  	golang.org/x/mobile/bind	15.632s
 λ ~/go/src/golang.org/x/mobile (issue/32008b): go test -v ./bind/
=== RUN   TestGenObjc
--- PASS: TestGenObjc (0.12s)
=== RUN   TestGenJava
--- PASS: TestGenJava (6.97s)
=== RUN   TestGenGo
--- PASS: TestGenGo (0.06s)
=== RUN   TestGenGoJavaWrappers
--- PASS: TestGenGoJavaWrappers (6.84s)
=== RUN   TestGenGoObjcWrappers
--- PASS: TestGenGoObjcWrappers (1.71s)
=== RUN   TestCustomPrefix
--- PASS: TestCustomPrefix (0.05s)
=== RUN   TestLowerFirst
--- PASS: TestLowerFirst (0.00s)
=== RUN   TestCapitalize
--- PASS: TestCapitalize (0.00s)
=== RUN   TestSelectorExprTypeName
--- PASS: TestSelectorExprTypeName (0.00s)
PASS
ok  	golang.org/x/mobile/bind	(cached)

我在这里提交了一个PR:

  • 修复ObjC的setter生成并更新golden文件mobile#34(评论)
y0u0uwnf

y0u0uwnf6#

https://golang.org/cl/186978提到了这个问题:bind: Fix setter name generation for ObjC

相关问题