最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ios - EXC_BAD_ACCESS when calling retro_load_game from a C library (dylib) in Swift using dlsym - Stack Overflow

programmeradmin1浏览0评论

I’m trying to integrate the VICE emulator’s libretro core (vice_x64sc_libretro_ios.dylib) into my iOS app using Swift. The core provides a function retro_load_game that I load dynamically using dlsym(). However, when I try to call this function, I get a crash (EXC_BAD_ACCESS).

From the VICE emulator source code, the function I’m trying to call is defined as:

bool retro_load_game(const struct retro_game_info *game);

The retro_game_info struct is defined as:

struct retro_game_info {
   const char *path;  // UTF-8 encoded file path
   const void *data;  // Memory buffer of the game file (NULL if fullpath mode is used)
   size_t size;       // Size of the memory buffer
   const char *meta;  // Meta information (NULL if not used)
};

I load the .dylib, get a pointer to retro_load_game, and then call it with a properly allocated retro_game_info struct:

import UIKit

class ViewController: UIViewController {
    var core: UnsafeMutableRawPointer?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupEmulator()
    }

    func setupEmulator() {
        let corePath = Bundle.main.bundlePath + "/Frameworks/vice_x64sc_libretro_ios.dylib"

        if FileManager.default.fileExists(atPath: corePath) {
            core = dlopen(corePath, RTLD_LAZY)
            if core == nil {
                return
            }

            if let filePath = Bundle.main.path(forResource: "SomePrg", ofType: "prg") {
                loadGame(filePath)
            }
        }
    }

    func loadGame(_ filePath: String) {
        guard let core = self.core else {
            return
        }

        if let retroLoadGamePtr = dlsym(core, "retro_load_game") {
            typealias RetroLoadGameFunc = @convention(c) (UnsafeRawPointer?) -> Int32
            let retroLoadGame = unsafeBitCast(retroLoadGamePtr, to: RetroLoadGameFunc.self)

            if let fileData = try? Data(contentsOf: URL(fileURLWithPath: filePath)) {
                let pathCString = strdup(filePath)
                let dataPointer = malloc(fileData.count)

                if let pathCString = pathCString, let dataPointer = dataPointer {
                    fileData.copyBytes(to: dataPointer.assumingMemoryBound(to: UInt8.self), count: fileData.count)

                    var gameInfo = retro_game_info(
                        path: pathCString,
                        data: dataPointer,
                        size: fileData.count,
                        meta: nil
                    )

                    let result = retroLoadGame(UnsafeRawPointer(&gameInfo))  //  Crashes here

                    free(pathCString)
                    free(dataPointer)
                }
            }
        }
    }
}

struct retro_game_info {
    let path: UnsafePointer<CChar>?
    let data: UnsafeRawPointer?
    let size: size_t
    let meta: UnsafePointer<CChar>?
}

I get EXC_BAD_ACCESS (code=1, address=0x0) at:

let result = retroLoadGame(UnsafeRawPointer(&gameInfo))

I have checked:

  • dlopen() successfully loads the .dylib
  • dlsym() successfully finds retro_load_game
  • gameInfo.path and gameInfo.data are allocated before calling retro_load_game
  • I free allocated memory after the function call

So:

  • Is my Swift retro_game_info struct correctly matching the C struct?
  • Is UnsafeRawPointer(&gameInfo) the right way to pass this struct to retro_load_game?
  • Am I missing any memory alignment issues that could cause EXC_BAD_ACCESS?
  • Is there a better way to debug why retro_load_game is failing?
发布评论

评论列表(0)

  1. 暂无评论