我是一个使用swift的ios开发人员。
我正在使用一个sdk来与ip摄像机通信,从中检索数据,并显示给用户。
我有一个sdk附带的项目,它是用obj c编写的,工作正常。问题是我无法将参数从函数传递到预期的参数类型。
sdk很老了,我使用静态库和桥接头集成了它,并且能够成功地连接到相机。我认为sdk是用c或c++编写的,基本上我在参数转换方面有问题。
Fos.h系列

typedef struct
{
int                       channel;
long long                 time;
unsigned int              index;
FOSMEDIATYPE              type;     //Is video or audio
FOSDECFMT                 fmt;      //The format of video or audio.
short                     isKey;
short                     multiAudioPage;
int                       frameTag;
union{
    FOSVIDEO_INFO      video;       //Media type is video.
    FOSAUDIO_INFO      audio;       //Media type is audio.
} media;
unsigned long long      pts;        //Pts.
unsigned int              len;      //Size of data.
char                      data[0];  //Just data.
}ATTRIBUTE_PACKED FOSDEC_DATA;    //Save the video or audio data,include video or audio information.

是的。
目标C职能,目前正在运作
- (IBAction)login:(id)sender {
//[self._imageView add]
NSString* str = [self._textField text];
const char* url = [str UTF8String];
char ip[128];
int port;
char usr[64];
char pwd[64];
int count = sscanf(url, "%[^:]:%d/%[^:]:%s", ip, &port, usr, pwd);
if (count != 4) {
    return;
}

mHandle = FosSdk_Create(ip, "", usr, pwd, port, port, FOSIPC_H264, FOSCNTYPE_IP);
//mHandle = FosSdk_Create(ip, "FASDFDSAFDASFASD", usr, pwd, port, port, FOSIPC_H264, FOSCNTYPE_P2P);
if (mHandle == FOSHANDLE_INVALID) {
    return;
}
[self._Login setEnabled:NO];
[self._Logout setEnabled:YES];

[NSThread detachNewThreadSelector:@selector(RunInThread:) toTarget:self withObject:^(void *param){

    int usrPrivilege = 0;
    FOSCMD_RESULT ret = FosSdk_Login(mHandle, &usrPrivilege, 500);
    if (FOSCMDRET_OK != ret) {
        return;
    }

    ret = FosSdk_OpenVideo(mHandle, FOSSTREAM_SUB, 500);
    if (FOSCMDRET_OK != ret) {
        return;
    }
    //char* framebuf = (char*)malloc(512*1024);
    FOSDEC_DATA* data = NULL;

    int outlen = 0;
    while (mHandle) {
// FosSdk_RetainHandle(mHandle, &usrPrivilege);
        if ( FOSCMDRET_OK == FosSdk_GetVideoData(mHandle, (char**)&data, &outlen, FOSDECTYPE_RGB24) && outlen>0)
        {

            if (data->type == FOSMEDIATYPE_VIDEO) {
                //int a=0;
                //a++;
                [self imageFromAVPicture:data->data width:data->media.video.picWidth height:data->media.video.picHeight];
            }
            else{
            }
        }
        usleep(20*1000);
    }
 }];
}

是的。
fos.h中的方法签名
    FOSSDK FOSCMD_RESULT FOSAPI FosSdk_GetVideoData(FOSHANDLE handle, char **data, int *outLen, FOSDECFMT videoFmt);

是的。
从objective-c调用时
FosSdk_GetVideoData(<#unsigned int handle#>, <#char **data#>, <#int *outLen#>, <#FOSDECFMT videoFmt#>)
}];

是的。
从斯威夫特那里打电话来
FosSdk_GetVideoData(handle: UInt32,
                   data: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!,
                   outLen: UnsafeMutablePointer<Int32>!,
                   videoFmt: FOSDECFMT)

是的。
错误是数据参数,确切地说:
Cannot convert value of type 'UnsafeMutablePointer<FOSDEC_DATA>' to expected argument type 'UnsafeMutablePointer<Int8>?'

是的。
我试过把数据声明改成这个,但是它给了我一个错误
let data = UnsafeMutablePointer<Int8>(&fosdecData)
Ambiguous use of 'init'

是的。
这个指针的东西有点复杂,但是我可以将我的设备与相机配对,使用的方法也使用了不可替换的指针。
但是,我不知道如何将这个empy数据对象传递给函数。
sdk已经过时,而且文档记录不好,这没有帮助。
不管怎样,我要让它起作用。
希望能得到一些帮助,谢谢编码!
是的。
编辑,多亏了ooper
是的。
这是swift中的更新版本,它实际上会产生一个意外错误。函数返回的结果现在是0,因此是正确的。但是,尝试访问原始的fosdedata结构时,由于信号:分段错误:11,我有一个命令失败。
我怎么能解决这个问题?很抱歉问了这么久,我想说得准确一点。
var mhandle : UInt32 = FOS_HANDLE_INIT.rawValue

override func viewDidLoad() {
    super.viewDidLoad()

    //These functions basically do camera pairing, and write result on mhandle, which is equal to 0 , if functions work, otherwise 1
    initializeFOS()
    startEzLinkFOS()
    sdkCreateFOS()
    loginFOS()
    openVideoFOS()

    var data: UnsafeMutablePointer<FOSDEC_DATA>? = nil
    var outlen : Int32 = 0
    while self.mhandle > 0 {
        let resultOOPer = withUnsafeMutablePointer(to: &data) { pointerToFosdecData in
            pointerToFosdecData.withMemoryRebound(to: UnsafeMutablePointer<Int8>?.self, capacity: 1, { (pointerToInt8Pointer) in

                FosSdk_GetVideoData(self.mhandle, pointerToInt8Pointer, &outlen, FOSDECTYPE_RGB24)
            })
        }

        if resultOOPer == FOSCMDRET_OK && outlen > 0{
            if let unwrData = data {

                //if unwrData.pointee.type == FOSMEDIATYPE_VIDEO{
                //Produced Output when i try access pointee, which is actually the fosdecData struct i need:
                //Command failed due to signal: Segmentation fault: 11
                //}
            }
        }
        usleep(20*1000)
    }


}

最佳答案

首先,以这种方式使用UnsafeMutablePointer的初始值设定项可能会产生意外的结果,您永远不应该这样做:

let data = UnsafeMutablePointer<FOSDEC_DATA>(&fosdecData)

swift编译器可以为inout参数准备一个临时区域,并传递该区域的地址,该地址在调用后立即释放。不幸的是,这段代码在某些情况下可以工作,但是您知道代码在某些情况下工作可能是一个很难修复的错误。
其次,在objective-c代码中,将data声明为FOSDEC_DATA*--指向FOSDEC_DATA--的指针,并将其初始化为NULL
为什么要用data初始化您的swift版本?您的objective-c代码中没有&fosdecData
声明fosdecData的等效swift代码应如下:
var data: UnsafeMutablePointer<FOSDEC_DATA>? = nil

您应该将data声明为data--指向UnsafeMutablePointer<FOSDEC_DATA>?--的指针,并将其初始化为FOSDEC_DATA
此外,它需要nil,您的var会将其重写为指向FosSdk_GetVideoData的有效指针。
第三,您需要将FOSDEC_DATA传递到UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!的第二个参数,但是FosSdk_GetVideoData将生成&data类型的指针。
要进行这种指针类型转换,需要使用UnsafeMutablePointer<UnsafeMutablePointer<FOSDEC_DATA>?>。你需要调用withMemoryRebound<T, Result>(to:capacity:_:)来获得指向withUnsafeMutablePointer<T, Result>(to:_:)的指针。
let result = withUnsafeMutablePointer(to: &data) {
    pointerToFosdecDataPtr in
    //pointerToFosdecDataPtr: UnsafeMutablePointer<UnsafeMutablePointer<FOSDEC_DATA>?>
    pointerToFosdecDataPtr.withMemoryRebound(to: UnsafeMutablePointer<Int8>?.self, capacity: 1) {
        pointerToInt8Ptr in
        //pointerToInt8Ptr: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
        //...
    }
}

所以,你的swift代码和objective-c代码是类似的:
var data: UnsafeMutablePointer<FOSDEC_DATA>? = nil
var outlen: Int32 = 0

while mHandle != 0 {

    let result = withUnsafeMutablePointer(to: &data) {
        pointerToFosdecDataPtr in
        //pointerToFosdecDataPtr: UnsafeMutablePointer<UnsafeMutablePointer<FOSDEC_DATA>?>
        pointerToFosdecDataPtr.withMemoryRebound(to: UnsafeMutablePointer<Int8>?.self, capacity: 1) {
            pointerToInt8Ptr in
            //pointerToInt8Ptr: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>
            FosSdk_GetVideoData(mHandle, pointerToInt8Ptr, &outlen, FOSDECTYPE_RGB24)
            //Implicit `return` works here and the result is passed to `result`.
        }
    }
    if result == FOSCMDRET_OK && outlen > 0 {
        if let data = data, data.pointee.type == FOSMEDIATYPE_VIDEO {
            //...
            //self.imageFromAVPicture...
        } else {
        }
    }
    usleep(20*1000)
}

编辑
更新代码以反映当前工作目标C代码的整个行为。(在objective-c代码中将data重命名为mhandle。)

关于objective-c - 将UnsafeMutablePointer传递给函数时出错,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45324330/

10-10 15:37