diff --git a/app/HGProductionTool/HGProductionTool.pro b/app/HGProductionTool/HGProductionTool.pro index 592561a..1d90fc2 100644 --- a/app/HGProductionTool/HGProductionTool.pro +++ b/app/HGProductionTool/HGProductionTool.pro @@ -25,6 +25,7 @@ win32 { contains(QT_ARCH, i386) { LIBS += -L../../../sdk/lib/win/x86/Release -lHGBase -lHGImgFmt -lHGImgProc LIBS += -L../../../sdk/lib/win/x86/OEM/huagao -lsane + LIBS += -L../../code/base/Debug/ -ltest CONFIG(release, debug|release) { LIBS += -L../../db/Release -lHGPdtToolDb DESTDIR = ../../../release/win/x86/Release @@ -36,7 +37,6 @@ win32 { contains(QT_ARCH, x86_64){ LIBS += -L../../../sdk/lib/win/x64/Release -lHGBase -lHGImgFmt -lHGImgProc LIBS += -L../../../sdk/lib/win/x64/OEM/huagao -lsane - CONFIG(release, debug|release) { LIBS += -L../../db/x64/Release -lHGPdtToolDb DESTDIR = ../../../release/win/x64/Release @@ -62,8 +62,10 @@ SOURCES += \ dialog_uploadcfgfile.cpp \ form_maininterface.cpp \ form_texttips.cpp \ + hgscanner.cpp \ main.cpp \ - mainwindow.cpp + mainwindow.cpp \ + ui_helper.cpp HEADERS += \ HGImgView.h \ @@ -76,7 +78,9 @@ HEADERS += \ dialog_uploadcfgfile.h \ form_maininterface.h \ form_texttips.h \ - mainwindow.h + hgscanner.h \ + mainwindow.h \ + ui_helper.h FORMS += \ dialog_accountmanage.ui \ diff --git a/app/HGProductionTool/ProductionTool_zh_CN.qm b/app/HGProductionTool/ProductionTool_zh_CN.qm index ff789a1..634121b 100644 Binary files a/app/HGProductionTool/ProductionTool_zh_CN.qm and b/app/HGProductionTool/ProductionTool_zh_CN.qm differ diff --git a/app/HGProductionTool/ProductionTool_zh_CN.ts b/app/HGProductionTool/ProductionTool_zh_CN.ts index 5bf13d1..d0fd2b0 100644 --- a/app/HGProductionTool/ProductionTool_zh_CN.ts +++ b/app/HGProductionTool/ProductionTool_zh_CN.ts @@ -257,7 +257,7 @@ select file - 选择目录 + 选择文件 diff --git a/app/HGProductionTool/analysisjson.cpp b/app/HGProductionTool/analysisjson.cpp index 17753fa..d9cdf7f 100644 --- a/app/HGProductionTool/analysisjson.cpp +++ b/app/HGProductionTool/analysisjson.cpp @@ -4,6 +4,7 @@ #include #include #include +#include AnalysisJson::AnalysisJson(QString path) { @@ -23,7 +24,13 @@ std::vector AnalysisJson::GetNode() if(!m_json.isObject()) return nodes; auto obj = m_json.object(); - for(auto key : obj.keys()) + + auto keys = obj.keys().toVector(); + std::sort(keys.begin(),keys.end(),[](QString x,QString y){ + return x.toInt()setupUi(this); + setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); } Dialog_uploadCfgFile::~Dialog_uploadCfgFile() diff --git a/app/HGProductionTool/hgscanner.cpp b/app/HGProductionTool/hgscanner.cpp new file mode 100644 index 0000000..c38032d --- /dev/null +++ b/app/HGProductionTool/hgscanner.cpp @@ -0,0 +1,38 @@ +#include "hgscanner.h" + +hgscanner::hgscanner(SANE_Handle h):devHandle_(h) +{ +} + +hgscanner::~hgscanner() +{ +} + +parameter* hgscanner::get_user_input(data_from from, value_type type, const wchar_t* title, const wchar_t* desc) +{ + + return nullptr; +} + +void hgscanner::test_callback(const wchar_t* name, test_event ev, void* data, size_t flag) +{ + +} + +int hgscanner::register_sane_callback(sane_callback cb, void* param) +{ + + return 0; +} + +int hgscanner::unregister_sane_callback(sane_callback cb) +{ + + return 0; +} + +int hgscanner::io_control(unsigned long code, void* data, unsigned* len) +{ + sane_io_control(devHandle_, code, data, len); + return 0; +} \ No newline at end of file diff --git a/app/HGProductionTool/hgscanner.h b/app/HGProductionTool/hgscanner.h new file mode 100644 index 0000000..8eb2f3d --- /dev/null +++ b/app/HGProductionTool/hgscanner.h @@ -0,0 +1,20 @@ +#pragma once +#include "sane/sane_ex.h" +#include "ui_helper.h" +#include "test_base.h" +class hgscanner :public ui_helper +{ +public: + hgscanner(SANE_Handle h); + ~hgscanner(); + virtual parameter* get_user_input(data_from from, value_type type, const wchar_t* title, const wchar_t* desc = NULL); + virtual void test_callback(const wchar_t* name/*test name*/, test_event ev, void* data, size_t flag); + virtual int register_sane_callback(sane_callback cb, void* param); + virtual int unregister_sane_callback(sane_callback cb); + virtual int io_control(unsigned long code, void* data, unsigned* len); + + +private: + SANE_Handle devHandle_; +}; + diff --git a/app/HGProductionTool/mainwindow.cpp b/app/HGProductionTool/mainwindow.cpp index 30a8308..d20e837 100644 --- a/app/HGProductionTool/mainwindow.cpp +++ b/app/HGProductionTool/mainwindow.cpp @@ -7,6 +7,7 @@ #include "dialog_changepwd.h" #include "dialog_accountmanage.h" #include "dialog_uploadcfgfile.h" +#include "hgscanner.h" MainWindow::MainWindow(HGPdtToolDbUserMgr userMgr, QWidget *parent) : QMainWindow(parent) @@ -16,11 +17,18 @@ MainWindow::MainWindow(HGPdtToolDbUserMgr userMgr, QWidget *parent) , m_top_splitter(nullptr) , m_bot_splitter(nullptr) , m_splitterCount(1) + , m_handle(nullptr) , m_isLogOut(false) { ui->setupUi(this); setWindowIcon(QIcon(":image/image_rsc/logo/logo.ico")); + connect(this, SIGNAL(sane_dev_arrive(QString)), this, SLOT(on_sane_dev_arrive(QString)), Qt::QueuedConnection); + connect(this, SIGNAL(sane_dev_remove(QString)), this, SLOT(on_sane_dev_remove(QString)), Qt::QueuedConnection); + + SANE_Int v = 0; + sane_init_ex(&v, sane_ex_callback, this); + HGUInt userType = 0; HGPdtToolDb_GetUserType(m_pdtToolDbuserMgr, &userType); if (userType == HGPDTTOOLDB_USERTYPE_NORMAL) @@ -56,6 +64,64 @@ bool MainWindow::isExitApp() return !m_isLogOut; } +int MainWindow::sane_ex_callback(SANE_Handle hdev, int code, void *data, unsigned int *len, void *param) +{ + (void)hdev; + (void)len; + MainWindow *p = (MainWindow *)param; + switch (code) + { + case SANE_EVENT_DEVICE_ARRIVED: + { + SANE_Device_Ex* sane_dev = (SANE_Device_Ex*)data; + emit p->sane_dev_arrive(sane_dev->name); + } + break; + case SANE_EVENT_DEVICE_LEFT: + { + SANE_Device* sane_dev = (SANE_Device*)data; + emit p->sane_dev_remove(sane_dev->name); + } + break; + } + + return 0; +} + +std::vector MainWindow::getDevices() +{ + std::vector name; + const SANE_Device** devs_list; + SANE_Status status = SANE_STATUS_GOOD; + if ((status = sane_get_devices(&devs_list, SANE_TRUE)) != SANE_STATUS_GOOD) + { + name.push_back(""); + return name; + } + name.clear(); + while (*devs_list != NULL) + { + name.push_back((*devs_list)->name); + devs_list++; + } + return name; +} + +void MainWindow::on_sane_dev_arrive(QString devName) +{ + SANE_Status ret = sane_open(devName.toStdString().c_str(), &m_handle); + + ui_helper* helper; + hgscanner* hg = new hgscanner(m_handle); + helper = dynamic_cast(hg); + func_test_go(L"test-31", L"null", helper); +} + +void MainWindow::on_sane_dev_remove(QString devName) +{ + +} + void MainWindow::on_act_newDevice_triggered() { m_splitterCount++; @@ -156,6 +222,6 @@ QString MainWindow::getLogInfo(HGResult ret) void MainWindow::on_act_upload_triggered() { - Dialog_uploadCfgFile dlg(m_pdtToolDbuserMgr, this); - dlg.exec(); + // Dialog_uploadCfgFile dlg(m_pdtToolDbuserMgr, this); + //dlg.exec(); } diff --git a/app/HGProductionTool/mainwindow.h b/app/HGProductionTool/mainwindow.h index 66ebf36..f41c7bf 100644 --- a/app/HGProductionTool/mainwindow.h +++ b/app/HGProductionTool/mainwindow.h @@ -6,12 +6,12 @@ #include #include #include "HGPdtToolDb.h" - +#include "sane/sane_ex.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE -class MainWindow : public QMainWindow +class MainWindow : public QMainWindow { Q_OBJECT @@ -20,9 +20,22 @@ public: ~MainWindow(); static QString getLogInfo(HGResult ret); - bool isExitApp(); + +private: + static int sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param); + + std::vector getDevices(); + +signals: + void sane_dev_arrive(QString devName); + void sane_dev_remove(QString devName); + +private slots: + void on_sane_dev_arrive(QString devName); + void on_sane_dev_remove(QString devName); + private slots: void on_act_newDevice_triggered(); @@ -41,6 +54,7 @@ private slots: private: QSplitter *m_top_splitter; QSplitter *m_bot_splitter; + SANE_Handle m_handle; int m_splitterCount; bool m_isLogOut; diff --git a/app/HGProductionTool/ui_helper.cpp b/app/HGProductionTool/ui_helper.cpp new file mode 100644 index 0000000..8edac01 --- /dev/null +++ b/app/HGProductionTool/ui_helper.cpp @@ -0,0 +1,39 @@ +#include "ui_helper.h" + +size_t parameter::get_size(void) +{ + return size_t(); +} + +void* parameter::get_data(void) +{ + return nullptr; +} + + +int ui_helper::register_sane_callback(sane_callback cb, void* param) +{ + + return 0; +} +int ui_helper::unregister_sane_callback(sane_callback cb) +{ + return 0; +} +int ui_helper::io_control(unsigned long code, void* data, unsigned* len) +{ + + return 0; +} +ui_helper::ui_helper() +{ +} +parameter* ui_helper::get_user_input(data_from from, value_type type, const wchar_t* title, const wchar_t* desc) +{ + return nullptr; +} +void ui_helper::test_callback(const wchar_t* name/*test name*/, test_event ev, void* data, size_t flag) +{ + +} + diff --git a/app/HGProductionTool/ui_helper.h b/app/HGProductionTool/ui_helper.h new file mode 100644 index 0000000..15b1b61 --- /dev/null +++ b/app/HGProductionTool/ui_helper.h @@ -0,0 +1,95 @@ +#include +#include "sane/sane_ex.h" +#include +#include +#include +#pragma once +class ref +{ + volatile long ref_; +public: + ref() : ref_(1) + {} + +protected: + virtual ~ref() + {} + +public: + long add_ref(void) + { + return _InterlockedIncrement(&ref_); + } + long release(void) + { + long r = _InterlockedDecrement(&ref_); + + if (r == 0) + delete this; + + return r; + } +}; + +class parameter : public ref +{ +public: + parameter() + {} + +protected: + virtual ~parameter() + {} + +public: + virtual size_t get_size(void) =0; + virtual void* get_data(void) = 0; // return data pointer, bool*, int*, double*, (wchar_t*) +}; + + +class ui_helper : public ref +{ + + +public: + ui_helper(); +public: + virtual ~ui_helper() + {} +public: + + enum data_from + { + DATA_FROM_KNOWN = 0, // pre-defined data name, i.e. resulotion, paper, bright, ... + DATA_FROM_USER, // need a window for user inputing + }; + enum value_type + { + VAL_TYPE_BOOL = 0, + VAL_TYPE_INT, + VAL_TYPE_FLOAT, + VAL_TYPE_STRING, + VAL_TYPE_CUSTOM, // custom data, such as gamma table ... + }; + + // get testing parameter ... + virtual parameter* get_user_input(data_from from, value_type type + , const wchar_t* title // window title when from == DATA_FROM_USER, or parameter name when from == DATA_FROM_KNOWN + , const wchar_t* desc = NULL // description of the parameter if from was DATA_FROM_USER, unused in DATA_FROM_KNOWN + ) =0; + + enum test_event + { + TEST_EVENT_TIPS = 0, // messages in testing process, data is (wchar_t*), flag is unused + TEST_EVENT_xxx, // should be complemented ... + TEST_EVENT_RESULT, // test result, data is (wchar_t*)description, flag is (bool)result, true - test pass + }; + virtual void test_callback(const wchar_t* name/*test name*/, test_event ev, void* data, size_t flag)=0 ; + + // register/unregister sane callback, the sane_callback in UI module should dispatch the events to these registered callback + virtual int register_sane_callback(sane_callback cb, void* param) =0; + virtual int unregister_sane_callback(sane_callback cb) =0; + + // All IO operations are blocking + virtual int io_control(unsigned long code, void* data, unsigned* len) =0; +}; diff --git a/code/base/test.vcxproj b/code/base/test.vcxproj index be9ebb9..0dba4d3 100644 --- a/code/base/test.vcxproj +++ b/code/base/test.vcxproj @@ -71,7 +71,16 @@ - ..\..\..\sdk\include;$(IncludePath) + ..\..\..\sdk\include;..\..\app\HGProductionTool\;$(IncludePath) + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\sdk\include;..\..\app\HGProductionTool\;$(IncludePath) + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\sdk\include;..\..\app\HGProductionTool\; + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\sdk\include;..\..\app\HGProductionTool\; diff --git a/code/base/test_base.cpp b/code/base/test_base.cpp index f441f61..58abbca 100644 --- a/code/base/test_base.cpp +++ b/code/base/test_base.cpp @@ -12,7 +12,6 @@ static struct Test_Map const wchar_t* title; //"б" const int ver; io_code num; - }Test_Map_NO[] = { {HGPDTTOOLDB_NAME_DIAL_SWITCH ,HGPDTTOOLDB_TITLE_DIAL_SWITCH ,0,IO_CTRL_CODE_BASE}, @@ -46,11 +45,12 @@ Test_Map_Bool[] {HGPDTTOOLDB_NAME_REBOOT_DEVICE ,HGPDTTOOLDB_TITLE_REBOOT_DEVICE ,0,IO_CTRL_CODE_BASE}, {HGPDTTOOLDB_NAME_MECH_PAPER_FEEDING_INCLINATION,HGPDTTOOLDB_TITLE_MECH_PAPER_FEEDING_INCLINATION ,0,IO_CTRL_CODE_BASE}, {HGPDTTOOLDB_NAME_CLEAR_ROLLER_COUNT ,HGPDTTOOLDB_TITLE_CLEAR_ROLLER_COUNT,0,IO_CTRL_CODE_SET_CLEAR_ROLLER_COUNT}, + {HGPDTTOOLDB_NAME_SINGLE_PAGE_TEST_1 ,HGPDTTOOLDB_TITLE_SINGLE_PAGE_TEST_1,0,IO_CTRL_CODE_TEST_SINGLE}, }, Test_Map_String[] { - {HGPDTTOOLDB_NAME_CLEAR_ROLLER_COUNT ,HGPDTTOOLDB_TITLE_CLEAR_ROLLER_COUNT,0,IO_CTRL_CODE_SET_CLEAR_ROLLER_COUNT}, + {L"123" ,HGPDTTOOLDB_TITLE_CLEAR_ROLLER_COUNT,0,IO_CTRL_CODE_SET_CLEAR_ROLLER_COUNT}, }, Test_Map_Int[] { @@ -58,7 +58,7 @@ Test_Map_Int[] {HGPDTTOOLDB_NAME_CONFIGURE_SPEED_MODE ,HGPDTTOOLDB_TITLE_CONFIGURE_SPEED_MODE ,0,IO_CTRL_CODE_BASE}, {HGPDTTOOLDB_NAME_DORMANCY ,HGPDTTOOLDB_TITLE_DORMANCY ,0,IO_CTRL_CODE_SET_POWER_LEVEL}, {HGPDTTOOLDB_NAME_SKEW_GEAR ,HGPDTTOOLDB_TITLE_SKEW_GEAR,0,IO_CTRL_CODE_SET_SKEW_CHECK_VAL}, - {HGPDTTOOLDB_NAME_SINGLE_PAGE_TEST_1 ,HGPDTTOOLDB_TITLE_SINGLE_PAGE_TEST_1,0,IO_CTRL_CODE_TEST_SINGLE}, + {HGPDTTOOLDB_NAME_SINGLE_PAGE_TEST_2 ,HGPDTTOOLDB_TITLE_SINGLE_PAGE_TEST_2,0,IO_CTRL_CODE_TEST_SINGLE}, {HGPDTTOOLDB_NAME_SINGLE_PAGE_TEST_3 ,HGPDTTOOLDB_TITLE_SINGLE_PAGE_TEST_3,0,IO_CTRL_CODE_TEST_SINGLE}, {HGPDTTOOLDB_NAME_PRESSUER_TEST ,HGPDTTOOLDB_TITLE_PRESSUER_TEST ,0,IO_CTRL_CODE_BASE}, @@ -66,7 +66,7 @@ Test_Map_Int[] //test static std::string jsontext1("{\"1\":{\"name\":\"test-8\",\"ver\":1}}"); -int sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param) +int sane_ex_callback1(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param) { switch (code) { @@ -153,22 +153,23 @@ int get_json_config_file() fclose(fp); std::cout << buf << std::endl; } -int func_test_init(void* init) + +DECL_API(int) func_test_init(void* init) { return 0; } -int func_test_get_list(wchar_t* buf, size_t* len) +DECL_API(int) func_test_get_list(wchar_t* buf, size_t* len) { return str_to_wchar(jsontext1, buf, len); } -int func_test_go(const wchar_t* name, const wchar_t* oper, ui_helper* helper) +DECL_API(int) func_test_go(const wchar_t* name, const wchar_t* oper, ui_helper* helper) { if (!name || !oper || !helper) { return -1; } - helper->add_ref(); - helper->register_sane_callback(sane_ex_callback, NULL); + //helper->add_ref(); + helper->register_sane_callback(sane_ex_callback1, NULL); bool flag = false; wchar_t* des = NULL; @@ -185,16 +186,15 @@ int func_test_go(const wchar_t* name, const wchar_t* oper, ui_helper* helper) { SANE_Bool map_bool = true; unsigned int len = sizeof(SANE_Bool); - ret = helper->io_control(Test_Map_Bool[i].num,&map_bool, &len); + ret = helper->io_control(Test_Map_Bool[i].num,(void *)&map_bool, &len); if (ret == SCANNER_ERR_OK) { ev = ui_helper::TEST_EVENT_RESULT; helper->test_callback(Test_Map_Bool[i].name, ev, des, true); map_bool = false; ret = helper->io_control(Test_Map_Bool[i].num, &map_bool, &len); - - return SCANNER_ERR_OK; } + return SCANNER_ERR_OK; } else if(wcscmp(name, Test_Map_String[i].name) == 0) { @@ -209,11 +209,12 @@ int func_test_go(const wchar_t* name, const wchar_t* oper, ui_helper* helper) return SCANNER_ERR_OK; } } - helper->release(); - helper->unregister_sane_callback(sane_ex_callback); + ret = helper->io_control(IO_CTRL_CODE_RESTORE_SETTINGS, NULL, NULL); + //helper->release(); + //helper->unregister_sane_callback(sane_ex_callback); return SCANNER_ERR_OK; } -int func_test_uninit(void* uninit) +DECL_API(int) func_test_uninit(void* uninit) { return 0; } @@ -221,41 +222,4 @@ int func_test_uninit(void* uninit) -int main11() -{ - /*get_json_config_file(); - int ret = 0; - wchar_t* str_wchar = NULL; - size_t len = 0; - ret = func_test_get_list(str_wchar, &len); - if (ret == ERROR_INSUFFICIENT_BUFFER) - { - str_wchar = new wchar_t[len]; - ret = func_test_get_list(str_wchar, &len); - } - ret = func_test_go(L"test-5",L"start",NULL);*/ - //std::wcout << str_wchar << std::endl; - return 0; -} - -parameter* ui_helper::get_user_input(data_from from, value_type type, const wchar_t* title, const wchar_t* desc = NULL) -{ - -} -int ui_helper::register_sane_callback(sane_callback cb, void* param) -{ - return 0; -} -int ui_helper::unregister_sane_callback(sane_callback cb) -{ - return 0; -} -int ui_helper::io_control(unsigned long code, void* data, unsigned* len) -{ - return 0; -} -void ui_helper::test_callback(const wchar_t* name/*test name*/, test_event ev, void* data, size_t flag) -{ - -} \ No newline at end of file diff --git a/code/base/test_base.h b/code/base/test_base.h index 41699db..1dfd297 100644 --- a/code/base/test_base.h +++ b/code/base/test_base.h @@ -1,7 +1,8 @@ #pragma once #include "string" #include "sane/sane_ex.h" - +#include "ui_helper.h" +#include //////////////////////////////////////TITLE////////////////////////////////////// /* 拨码开关校验 */ #define HGPDTTOOLDB_TITLE_DIAL_SWITCH L"拨码开关校验" @@ -146,95 +147,7 @@ /* 清除滚轴计数 */ #define HGPDTTOOLDB_NAME_CLEAR_ROLLER_COUNT L"test-35" -class ref -{ - volatile long ref_; -public: - ref() : ref_(1) - {} - -protected: - virtual ~ref() - {} - -public: - long add_ref(void) - { - return _InterlockedIncrement(&ref_); - } - long release(void) - { - long r = _InterlockedDecrement(&ref_); - - if (r == 0) - delete this; - - return r; - } -}; - -class parameter : public ref -{ -public: - parameter() - {} - -protected: - virtual ~parameter() - {} - -public: - virtual size_t get_size(void) = 0; - virtual void* get_data(void) = 0; // return data pointer, bool*, int*, double*, (wchar_t*) -}; - - -class ui_helper : public ref -{ -public: - ui_helper() - {} -protected: - virtual ~ui_helper() - {} - -public: - enum data_from - { - DATA_FROM_KNOWN = 0, // pre-defined data name, i.e. resulotion, paper, bright, ... - DATA_FROM_USER, // need a window for user inputing - }; - enum value_type - { - VAL_TYPE_BOOL = 0, - VAL_TYPE_INT, - VAL_TYPE_FLOAT, - VAL_TYPE_STRING, - VAL_TYPE_CUSTOM, // custom data, such as gamma table ... - }; - - // get testing parameter ... - virtual parameter* get_user_input(data_from from, value_type type - , const wchar_t* title // window title when from == DATA_FROM_USER, or parameter name when from == DATA_FROM_KNOWN - , const wchar_t* desc = NULL // description of the parameter if from was DATA_FROM_USER, unused in DATA_FROM_KNOWN - ) = 0; - - enum test_event - { - TEST_EVENT_TIPS = 0, // messages in testing process, data is (wchar_t*), flag is unused - TEST_EVENT_xxx, // should be complemented ... - TEST_EVENT_RESULT, // test result, data is (wchar_t*)description, flag is (bool)result, true - test pass - }; - virtual void test_callback(const wchar_t* name/*test name*/, test_event ev, void* data, size_t flag) = 0; - - // register/unregister sane callback, the sane_callback in UI module should dispatch the events to these registered callback - virtual int register_sane_callback(sane_callback cb, void* param) = 0; - virtual int unregister_sane_callback(sane_callback cb) = 0; - - // All IO operations are blocking - virtual int io_control(unsigned long code, void* data, unsigned* len) = 0; -}; - +#define TEST_DLL #ifdef TEST_DLL #define DECL_API(ret) __declspec(dllexport) ret __stdcall #else