书接上文,上次返回的只有字符串,还是printf的结果,在python里没法用,需要把数据返回到python的工作区才行。
基本思想
通过队列,将获得的数据发送到另一个函数中,在python中调用另一个函数就行了,这个函数是可以有返回值的。
完整代码
#include "pch.h"
#include "pch.h"
#include "HWPuSDK.h"
#include <string>
#include <stdio.h>
#include <Windows.h>
#include <csignal>
#include <iostream>
#include< queue>
#include <mutex>
using namespace std;
//互斥锁要在之前初始化
mutex m_mutex;
queue<int> testQueue;
//初始化函数--返回值0代表失败1代表成功
BOOL CamInit()
{
// 初始化标记1为成功0为失败
BOOL INIT_FLAG = IVS_PU_Init(3, NULL, 6060);
//判断初始化是否成功
if (INIT_FLAG)
{
printf("%s\n", "init sdk success");
}
else
{
printf("%s\n", "init sdk failed");
//输出错误码
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "common error");
break;
case 5:
printf("%s\n", "SDK has been initialed");
break;
case 101:
printf("%s\n", "SDK init connection mode error");
break;
case 102:
printf("%s\n", "SDK init local IP error");
break;
default:
printf("%s\n", "unknown error");
break;
}
}
return INIT_FLAG;
}
// 登录返回函数--返回正整数代表获得id返回其他代表失败
ULONG CamLogin(CHAR* ip, CHAR* user, CHAR* password)
{
//返回正整数id
ULONG login_id = IVS_PU_Login(ip, 6060, user, password);
if (login_id > 0)
{
printf("%s\n", "get login id success");
}
else
{
printf("%s\n", "get login id failed");
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "common error");
break;
case 2:
printf("%s\n", "username or password error");
break;
case 4:
printf("%s\n", "SDK not init");
break;
case 6:
printf("%s\n", "SDK version not match equipment");
break;
case 7:
printf("%s\n", "params is NULL");
break;
case 10106:
printf("%s\n", "SDK password is init,please change");
break;
default:
printf("%s\n", "unknown error");
break;
}
}
return login_id;
}
void procMetaData(PU_META_DATA* pstMetaData)
{
INT target_type = 0;
INT target_condition = 0;
for (UINT uIndex = 0; uIndex < pstMetaData->usValidNumber; ++uIndex)
{
switch (pstMetaData->pstMetaUserData[uIndex].eType)
{
case 0x06000024: //目标类型 描述见数据结构
target_type = pstMetaData->pstMetaUserData[uIndex].unMetaData.IntValue;
break;
case 0x06000022: //目标状态 描述见数据结构
target_condition = pstMetaData->pstMetaUserData[uIndex].unMetaData.IntValue;
break;
default:
break;
}
}
m_mutex.lock();
if (target_condition == 0x00000002)
{
//printf(" TRIPWIRE\n");
if (target_type == 0x60)
{
//printf("CAR TRIPWIRE\n");
testQueue.push(100);
}
else if (target_type == 0x61)
{
//printf("UNCAR TRIPWIRE\n");
testQueue.push(200);
}
else if (target_type == 0x62)
{
//printf("PEOPLE TRIPWIRE\n");
testQueue.push(300);
}
}
m_mutex.unlock();
}
//实况回调函数
void CALLBACK fRealDataCallBack(CHAR* szBuffer, LONG lSize, VOID* pUsrData)
{
BOOL bRet = PU_FALSE;
//第二层元数据TYPE
PU_META_DATA* pstMetaTargetData = NULL;
bRet = IVS_User_GetMetaData(szBuffer, lSize, TARGET, &pstMetaTargetData);
if ((PU_TRUE == bRet) && (NULL != pstMetaTargetData))
{
//printf("%s%d%s\n", "数据长度为", lSize, "字节");
procMetaData(pstMetaTargetData);
IVS_User_FreeMetaData(&pstMetaTargetData);
}
}
//实况函数
ULONG Real(ULONG id)
{
//结构体赋值
PU_REAL_PLAY_INFO_S stRealPlayInfo = { 0 };
//通道号
stRealPlayInfo.ulChannelId = 101;
//传输类型
stRealPlayInfo.enProtocolType = PU_PROTOCOL_TYPE_TCP;
//码流类型
stRealPlayInfo.enStreamType = PU_VIDEO_MAIN_STREAM;
//保活
stRealPlayInfo.bKeepLive = TRUE;
//码流加密方式
stRealPlayInfo.enMediaCryptoType = PU_MEDIA_CRYPTO_NONE;
//数据类型
stRealPlayInfo.enVideoType = PU_VIDEO_TYPE_META;
//媒体回调类型
stRealPlayInfo.enMediaCallbackType = PU_MEDIA_CALLBACK_TYPE_META_FRAME;
//元数据返回标记位置
stRealPlayInfo.szReserved[22] = 1;
//只返回检测框内容
stRealPlayInfo.szReserved[23] = PU_METADATA_REQUEST_REST;
//返回元数据时句柄为空
stRealPlayInfo.hPlayWnd = NULL;
//调用实时预览函数
ULONG real_id = IVS_PU_RealPlay(id, &stRealPlayInfo, fRealDataCallBack, NULL);
if (real_id > 0)
{
printf("%s\n", "get realplay id success");
}
else
{
printf("%s\n", "get realplay id failed");
ULONG error_code = IVS_PU_GetLastError();
switch (error_code)
{
case 1:
printf("%s\n", "common error");
break;
case 4:
printf("%s\n", "SDK not init");
break;
case 9:
printf("%s\n", "connection error");
break;
case 10:
printf("%s\n", "message send timeout");
break;
case 11:
printf("%s\n", "message get timeout");
case 15:
printf("%s\n", "message get timeout");
break;
case 106:
printf("%s\n", "wrong user id");
break;
case 137:
printf("%s\n", "function use error");
break;
default:
printf("%s\n", "unknown error");
break;
}
}
return real_id;
}
//数据接收,在python中循环调用
extern "C" __declspec(dllexport) int recv()
{
int result = 0;
while (1)
{
//Sleep(100);
m_mutex.lock();
if (testQueue.size() == 0)
{
testQueue.push(0);
m_mutex.unlock();
return result;
}
else
{
result = testQueue.front();
testQueue.pop();
m_mutex.unlock();
return result;
}
}
}
//事件订阅
extern "C" __declspec(dllexport) int yxjc(CHAR * ip, CHAR * user, CHAR * password)
{
//初始化sdk
CamInit();
Sleep(1 * 1000);
//获得登录id
ULONG id = CamLogin(ip, user, password);
Sleep(1 * 1000);
//实时数据返回
int real_id = Real(id);
return real_id;
}
//登出
extern "C" __declspec(dllexport) BOOL out_log(ULONG id)
{
BOOL out_flag = IVS_PU_Logout(id);
return out_flag;
}
//清理sdk
extern "C" __declspec(dllexport) BOOL clean()
{
BOOL clean_flag = IVS_PU_Cleanup();
return clean_flag;
}
点击生成,获得dll文件,在python中就可以调用了。
本代码在python中调用需要用while循环去调用,没有返回目标检测结果会返回0,有返回目标检测结果会返回对应的整形值。
注意事项
1、要对队列加锁,且要放在if语句判断外面
2、python退出的时候顺便把登录和sdk清除了,接口我都写了,但是没做异常处理,需要用到的要自己写一下