在macOS桌面应用程序(XCode项目)中嵌入Racket静态库

问题描述 投票:2回答:1

[Internet上有article关于将手动构建的Racket库嵌入到iOS应用程序中。忽略这样一种可能性比它有趣而不是有用的事实,我遵循了说明,并且(ta-dah)能够创建一个可行的示例(令我惊讶!)。

无论如何,我非常渴望在macOS Xcode项目中重复一遍技巧。在Racket发行版中包含Racket.framework,它与gcc(和-framework选项)一起使用时很好,但是从XCode的角度来看,此框架没有有效的结构,xcodetools无法链接到该框架或使用codesign。

因此,我决定按照文章中的iOS说明进行操作,但对于macOS。我使用librktio构建了macOS Racket库(libracketlibmzgc./configure),但未指定主机和

  • make
  • make cgc && make install-cgc

((注:最终结果对于两个都是相同的。)。

我已经创建了互操作C源:

#include "scheme.h"
#include "interop.h"
#include "racketmac.c" // <- this is my rkt module made with raco ctool

static int init(Scheme_Env *e, int argc, char *argv[]) {
    declare_modules(e);

    return 0;
}

int init_racket() {
    return scheme_main_setup(1, init, 0, NULL);
}

和标题:

#ifndef Interop_h
#define Interop_h

int init_racket(void);

#endif /* Interop_h */

,然后将“ interop.h”添加到桥接头文件和来自Swift的C函数调用,如:

import Cocoa

final public class RacketInteractor: NSObject {

    public override init() {
        super.init()

        init_racket()
    }    
}

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    var interactor: RacketInteractor!

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        interactor = RacketInteractor()
    }

// ...

}

项目,macOS Cocoa应用程序,是可构建且可运行的。但是每次调用init_racket都会导致EXC_BAD_ACCESS。通过研究堆栈跟踪,我了解到方案解释器正在尝试发出“内存不足”错误(查找第5帧):

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x10ad2153d)
    frame #0: 0x000000010ad2153d
  * frame #1: 0x0000000100102814 RacketMapApp`scheme_native_stack_trace at jitstack.c:215:7 [opt]
    frame #2: 0x0000000100058f7b RacketMapApp`continuation_marks(p=0x000000010a3b1250, _cont=0x0000000000000000, econt=0x0000000000000000, mc=<unavailable>, prompt_tag=0x000000010a4001d0, who="continuation-marks", just_chain=0) at fun.c:7906:10 [opt]
    frame #3: 0x000000010002d565 RacketMapApp`do_raise(arg=0x000000010ac49028, need_debug=1, eb=180654120) at error.c:4606:13 [opt]
    frame #4: 0x0000000100028f8a RacketMapApp`scheme_raise_exn(id=17) at error.c:4402:3 [opt]
    frame #5: 0x000000010002c4f7 RacketMapApp`scheme_raise_out_of_memory(where=<unavailable>, msg=<unavailable>) at error.c:2541:3 [opt]
    frame #6: 0x00000001001a02af RacketMapApp`scheme_malloc_code [inlined] malloc_page(size=<unavailable>) at salloc.c:1047:5 [opt]
    frame #7: 0x00000001001a0271 RacketMapApp`scheme_malloc_code(size=35320) at salloc.c:1156 [opt]
    frame #8: 0x00000001001035ef RacketMapApp`scheme_generate_one(old_jitter=0x0000000000000000, generate=(RacketMapApp`scheme_do_generate_common at jitcommon.c:3576), data=0x0000000000000000, gcable=0, save_ptr=0x0000000000000000, ndata=0x0000000000000000) at jitstate.c:256:18 [opt]
    frame #9: 0x000000010008f593 RacketMapApp`create_native_lambda(lam=0x000000010ac5b348, clear_code_after_jit=1, case_lam=0x0000000000000000) at jit.c:4127:5 [opt]
    frame #10: 0x0000000100101f4b RacketMapApp`scheme_jit_closure(code=0x000000010ac5b308, context=0x0000000000000000) at jitprep.c:558:13 [opt]
    frame #11: 0x0000000100101abe RacketMapApp`jit_expr(expr=0x000000010a2e3c68) at jitprep.c:0 [opt]
    frame #12: 0x0000000100101cd9 RacketMapApp`jit_expr [inlined] define_values_jit(data=<unavailable>) at jitprep.c:301:12 [opt]
    frame #13: 0x0000000100101c82 RacketMapApp`jit_expr(expr=0x000000010ac48fe8) at jitprep.c:651 [opt]
    frame #14: 0x00000001001020ce RacketMapApp`scheme_jit_linklet(linklet=0x000000010a4bfb88, step=<unavailable>) at jitprep.c:704:9 [opt]
    frame #15: 0x00000001001088f4 RacketMapApp`instantiate_linklet_k at linklet.c:0 [opt]
    frame #16: 0x000000010004ffd9 RacketMapApp`scheme_top_level_do_worker(k=(RacketMapApp`instantiate_linklet_k at linklet.c:1325), eb=<unavailable>, new_thread=0) at fun.c:1314:11 [opt]
    frame #17: 0x000000010002450f RacketMapApp`scheme_basic_env [inlined] place_instance_init(stack_base=<unavailable>, initial_main_os_thread=1) at env.c:501:3 [opt]
    frame #18: 0x000000010002436b RacketMapApp`scheme_basic_env at env.c:214 [opt]
    frame #19: 0x000000010019f7f8 RacketMapApp`scheme_main_setup [inlined] call_with_basic(data=<unavailable>) at salloc.c:178:16 [opt]
    frame #20: 0x000000010019f7f3 RacketMapApp`scheme_main_setup [inlined] do_main_stack_setup(no_auto_statics=<unavailable>, data=<unavailable>) at salloc.c:203 [opt]
    frame #21: 0x000000010019f7c3 RacketMapApp`scheme_main_setup [inlined] scheme_main_stack_setup(no_auto_statics=<unavailable>, data=<unavailable>) at salloc.c:337 [opt]
    frame #22: 0x000000010019f758 RacketMapApp`scheme_main_setup(no_auto_statics=<unavailable>, _main=(RacketMapApp`init at interop.c:14), argc=0, argv=0x0000000000000000) at salloc.c:187 [opt]
    frame #23: 0x00000001000017fb RacketMapApp`@objc RacketInteractor.init() [inlined] RacketMapApp.RacketInteractor.init() -> RacketMapApp.RacketInteractor at RacketInteractor.swift:19:9 [opt]
    frame #24: 0x00000001000017bc RacketMapApp`@objc RacketInteractor.init() at <compiler-generated>:15 [opt]
    frame #25: 0x00000001000024ed RacketMapApp`@objc AppDelegate.applicationDidFinishLaunching(_:) [inlined] RacketMapApp.RacketInteractor.__allocating_init() -> RacketMapApp.RacketInteractor at <compiler-generated>:0 [opt]
    frame #26: 0x00000001000024e2 RacketMapApp`@objc AppDelegate.applicationDidFinishLaunching(_:) [inlined] RacketMapApp.AppDelegate.applicationDidFinishLaunching(self=0x0000600000004320) -> () at AppDelegate.swift:17 [opt]
    frame #27: 0x00000001000024e2 RacketMapApp`@objc AppDelegate.applicationDidFinishLaunching(_:) at <compiler-generated>:16 [opt]
    frame #28: 0x00007fff3443135f CoreFoundation`__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    frame #29: 0x00007fff344312f3 CoreFoundation`___CFXRegistrationPost1_block_invoke + 63
    frame #30: 0x00007fff34431268 CoreFoundation`_CFXRegistrationPost1 + 372
    frame #31: 0x00007fff34430ebe CoreFoundation`___CFXNotificationPost_block_invoke + 97
    frame #32: 0x00007fff344007e2 CoreFoundation`-[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1575
    frame #33: 0x00007fff343ffc82 CoreFoundation`_CFXNotificationPost + 1351
    frame #34: 0x00007fff36a85a02 Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 59
    frame #35: 0x00007fff3160b2ff AppKit`-[NSApplication _postDidFinishNotification] + 312
    frame #36: 0x00007fff3160b042 AppKit`-[NSApplication _sendFinishLaunchingNotification] + 208
    frame #37: 0x00007fff31608103 AppKit`-[NSApplication(NSAppleEventHandling) _handleAEOpenEvent:] + 549
    frame #38: 0x00007fff31607d49 AppKit`-[NSApplication(NSAppleEventHandling) _handleCoreEvent:withReplyEvent:] + 688
    frame #39: 0x00007fff36ab1226 Foundation`-[NSAppleEventManager dispatchRawAppleEvent:withRawReply:handlerRefCon:] + 308
    frame #40: 0x00007fff36ab1090 Foundation`_NSAppleEventManagerGenericHandler + 98
    frame #41: 0x00007fff357b5092 AE`___lldb_unnamed_symbol77$$AE + 2172
    frame #42: 0x00007fff357b47b9 AE`___lldb_unnamed_symbol76$$AE + 41
    frame #43: 0x00007fff357aca27 AE`aeProcessAppleEvent + 449
    frame #44: 0x00007fff32fa22b8 HIToolbox`AEProcessAppleEvent + 54
    frame #45: 0x00007fff3160215c AppKit`_DPSNextEvent + 1670
    frame #46: 0x00007fff31600690 AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352
    frame #47: 0x00007fff315f23ae AppKit`-[NSApplication run] + 658
    frame #48: 0x00007fff315c4775 AppKit`NSApplicationMain + 777
    frame #49: 0x0000000100001a29 RacketMapApp`main at AppDelegate.swift:12:7 [opt]
    frame #50: 0x00007fff6ba967fd libdyld.dylib`start + 1
    frame #51: 0x00007fff6ba967fd libdyld.dylib`start + 1

我尝试使用Interop源创建静态库,并将其添加到XCode项目中,结果相同。同时,创建的librktiolibracketlibmzgc完全可以与gcc cli一起使用。所以我很困惑,因为我什至不知道如何正确调试此类错误。也许我需要调整一些XCode构建选项?为什么支持iOS的库可以正常运行而不能支持macOS的库?是否有一种更简单的方法将Racket嵌入XCode macOS项目(例如,通过CMake生成)?

EDIT:在构建racket3m版本时,崩溃消息更加清晰,例如:

“警告:无法保护页面0x10a350000(os / kern)保护失败的16384个字节”

就像内存分配的系统调用一样,只是没有提供足够的资源,这很奇怪。

swift macos scheme racket
1个回答
0
投票

“警告:无法保护页面0x10a350000(os / kern)保护失败的16384个字节”

当您的应用缺少“允许未签名的可执行内存”授权时发生。确保您的应用具有该权限和“ Allow JIT”权利。

但是一旦您克服了这一点,您就会遇到Racket 3m的GC写屏障,我在本文中对此做了简要介绍。为了使它在调试模式下工作,您必须在lldb中注册一个信号处理程序,以便在发生预期的SIGSEGV时通过。不幸的是,有一个LLDB bug,这是行不通的。

© www.soinside.com 2019 - 2024. All rights reserved.