转换Int8?到UnsafePointer <int8>?

时间:2019-04-10 23:44:51

标签: c swift xcode

我对Swift非常陌生。尝试编写一个调用外部C方法的Swift应用。但是,Xcode编译器给出有关类型转换的错误。 C方法原型的形式为:

void * cMethod(const char* string1Path, const char* string2Path, const char* string3Path, const char* string4Path);

Swift代码的要旨是:

import OpenGLES
import CoreGraphics
import GLKit

var mGLUTWindow: Void?

class myClass {

    mGLUTWindow = nil
    let appBundle = Bundle.main

    let string1 = appBundle.path(forResource: "Init", ofType: "dat")
    let string1Path = Int8((string1?.description)!)

    let string2 = appBundle.path(forResource: "autostart", ofType: "type")
    let string2Path = Int8((string2?.description)!)

    let string3: String? = appBundle.path(forResource: "data", ofType: "") ?? "" + ("/")
    let string3Path = Int8((string3?.description)!)

    mGLUTWindow = cMethod(UnsafePointer(string3Path), string1Path, string2Path, "ios")
}

编译器给出错误:

Cannot convert value of type 'Int8?' to expected argument type 'UnsafePointer<Int8>?'

C方法由桥接头引入。有没有办法将其转换为预期的参数?

注意:此处的Swift代码是几年前从Objective-C文件带来的,并且已被改编为Swift。我使用this Obj-C转Swift转换器,因为我几乎不了解Swift,因此无法阅读Obj-C。我放入的Obj-C衬里的格式为:

NSString * string1 = [[appBundle pathForResource:@"data" ofType:@""] stringByAppendingString:@"/"]; 
const char * string1Path = [string1 cStringUsingEncoding:[NSString defaultCStringEncoding]];

2 个答案:

答案 0 :(得分:1)

尽管将Int8?转换为指针很简单(只需将其解包并在将其作为参数传递时使用&运算符),但是您真正的问题是将字符串转换为{{ 1}}首先是一个错误。 Int8返回的值将是一条路径,看起来像这样:

Bundle.path(forResource:ofType:)

同时,您尝试将其转换为"/Applications/MyApp.app/Contents/Resources/Init.dat" ,这是一种整数类型,可以使用带有Int8的初始化程序来存储-128到127之间的值。该初始化程序返回可选内容的原因是因为并非每个字符串都包含-128到127之间的数字,所以如果该字符串是其他字符串,则会得到String

nil"37"这样的字符串可以正确转换,但是上面的路径字符串始终只会给您"-101"

您实际上想要在此处执行的操作是将nil转换为C字符串。有几种不同的方法可以做到这一点,但是我会使用String的{​​{1}}功能,就像这样:

URL

请注意,由于未将fileSystemRepresentation定义为不在该范围内有效,因此请确保此处不要让let url1 = appBundle.url(forResource: "Init", withExtension: "dat")! // instead of path url1.withUnsafeFileSystemRepresentation { cPath in // cPath here is an UnsafePointer<Int8> that you can pass to C APIs inside this block. } // Don't let cPath get out here or bad things will happen. 转义cPath块。

还要注意,由于withUnsafeFileSystemRepresentation,如果!文件实际上不存在于您的应用程序中,这将使您的应用程序崩溃,因此,最好确保将其包括在内。

答案 1 :(得分:1)

如果为我提供了C函数,并在您的Objective-C行中显示了一些代码,我会写这样的东西:


var mGLUTWindow: UnsafeRawPointer?

class MyClass {

    func aMethod() {
        let appBundle = Bundle.main

        let string1 = appBundle.path(forResource: "Init", ofType: "dat")!

        let string2 = appBundle.path(forResource: "autostart", ofType: "type")!

        let string3 = (appBundle.path(forResource: "data", ofType: "") ?? "") + ("/")

        mGLUTWindow = UnsafeRawPointer(cMethod(string3, string1, string2, "ios"))
    }
}

在Swift中,当您将String传递给类型char *的参数时,Swift会生成一个临时的C字符串缓冲区并传递该缓冲区的地址,您无需调用{ {1}}。

如果const char * string1Path = [string1 cStringUsingEncoding:[NSString defaultCStringEncoding]];保留了任何指针供以后使用,则您可能需要更复杂的代码,但是尚不清楚我们是否需要像当前说明那样的复杂代码。