我是一名使用swift的ios开发人员。 我正在使用sdk与ip camera通信,从中检索数据,并将其显示给用户。 我用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#>)
}];
从swift
调用时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'
这个指针的东西有点复杂,但我能够将我的设备与相机配对,使用的方法也使用了unsafeMutablePointers。 但是,我无法弄清楚如何将这个empy数据对象传递给函数。
SDK过时且记录错误,但没有帮助。 无论如何,我需要让它工作。 希望得到一些帮助,谢谢编码员!
编辑,感谢OOPer 。 这是swift中的更新版本,实际上会产生意外错误。从函数返回的结果现在为0,所以它是正确的。但是,尝试访问原始FosdedData结构时,由于信号:命令失败,因为信号:分段错误: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)
}
}
答案 0 :(得分:0)
首先,以这种方式使用UnsafeMutablePointer
的初始值设定项可能会产生意外结果,您绝不应该这样做:
let data = UnsafeMutablePointer<FOSDEC_DATA>(&fosdecData)
Swift编译器可以为inout参数准备一个临时区域,并传递该区域的地址,该地址在调用后立即释放。不幸的是,这些代码在某些情况下可能会起作用,但是您知道代码中的代码可能是一个难以修复的错误。
其次,在您的Objective-C代码中,您将data
声明为FOSDEC_DATA*
- 指向FOSDEC_DATA
的指针 - 并将其初始化为NULL
强>
为什么要尝试使用data
初始化您的Swift版&fosdecData
?您的Objective-C代码中没有fosdecData
。
data
声明的等效Swift代码应如下所示:
var data: UnsafeMutablePointer<FOSDEC_DATA>? = nil
您应将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:_:)
以获取指向data
的指针。
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>?>
//...
}
}
因此,与您的Objective-C代码等效的Swift代码将是这样的:
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)
}
修改强>
代码已更新,以反映当前正在运行的 Objective-C代码的整体行为。 (与Objective-C代码一样,将mhandle
重命名为mHandle
。)