2017-07-26 13 views
1

私はswiftを使用するiosの開発者です。 私はipカメラと通信するためにsdkを使用して、そこからデータを取得し、それをユーザに示します。 私はobj cで書かれたsdkに同梱されていて問題なく動作しているプロジェクトを出しました。問題は、関数から期待されるパラメータ型にパラメータを渡すことができないことです。 SDKは非常に古く、スタティックライブラリとブリッジヘッダーを使用してSDKを統合したため、カメラに正常に接続できました。私はsdkはCまたはC + +で書かれていると思う、と私は基本的にパラメータの変換に問題がある。UnsafeMutablePointerを関数に渡すときのエラー

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. 

。現在

- (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); 
    } 
}]; 
} 

作業

Objective Cの関数。

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' 

私は、このエラーが発生します。

このポインタのものは少し複雑ですが、unsafeMutablePointerも使用していた方法を使ってデバイスをカメラとペアリングすることができました。 しかし、私はこの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

まず、このようにUnsafeMutablePointerの初期化子を使用すると、予期しない結果を生成することができ、あなたがやるべきではありません:

let data = UnsafeMutablePointer<FOSDEC_DATA>(&fosdecData) 

スウィフトコンパイラはINOUTパラメータとパスのための一時的な領域とを準備することができます呼び出し直後に解放される領域のアドレス。残念ながら、このコードはいくつかのケースでは動作するかもしれませんが、work-in-some-caseのコードは修正するのが難しいかもしれません。ポインタへFOSDEC_DATA - -


第二に、あなたのObjective-Cのコードでは、あなたはdataFOSDEC_DATA*として宣言NULLにそれを初期化します。

なぜdataのSwiftバージョンを&fosdecDataで初期化しようとしていますか? Objective-CコードにはfosdecDataはありません。

dataの宣言のための同等のスウィフトコードは次のようにする必要があります:

var data: UnsafeMutablePointer<FOSDEC_DATA>? = nil 

あなたはUnsafeMutablePointer<FOSDEC_DATA>?としてdataを宣言する必要があります - FOSDEC_DATAへのポインタを - とnilにそれを初期化します。

さらに、varである必要があります。FosSdk_GetVideoDataは、有効なポインタFOSDEC_DATAに書き換えます。


第三に、あなたはFosSdk_GetVideoDataの2番目のパラメータにUnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!を渡す必要がありますが、&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>?> 
     //... 
    } 
} 

だから、あなたの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) 
} 

全体を反映するように更新EDIT

コード現在動作しているの動作 Objective-Cコード。 (Objective-CコードのようにmhandlemHandleに改名されました。)

+0

ありがとうOOPer、このコードはコンパイラを幸せにしますが、結果は1です。このケースでは負です。この関数はエラーを返しています。 。 **また、** dataプロパティがnilで、data.pointeeにアクセスしようとするとエラーが発生しました**シグナルのためにコマンドが失敗しました:セグメンテーションフォールト:11 ** – Simone

+0

報告していただきありがとうございます。しかし、上記の私のコードは、 'let result = ...; if result == FOSCMDRET_OK {...} 'は、あなたのObjCコード' if(FOSCMDRET_OK == ...){...} 'に相当するマシンコードを出力します。あなたのObjCコードに相当するすべてのコードを記入しましたか?たとえば、私のコードでは、あなたの質問でその部分を参照していないので 'while(mHandle){...}'は省略されました。しかし、実際には、それが必要です。 API呼び出しの結果がOK以外の値を返した場合、APIはポインタ引数で指定された領域に影響を与えません。だから、 '1'を返してもOKでない場合、' data'はまだ 'nil'です。 – OOPer

+0

あなたは 'mHandle'がどのように宣言されているのか、値が与えられているのか表示していません。 SwiftコードでOK以外の結果が得られた場合は、Swiftコードの他の部分が間違っているためです。コードの関連部分を非表示にして、それらのすべてを表示しないでください。 – OOPer

関連する問題