Mình hiện giờ đang gặp rắc rồi về việc viết Palm Conduit bằng C\C++ (chứ không phải Java hay kiểu activeX COM) mà không sử dụng bất cứ công cụ biên dịch nào của Microsoft (cũng free nhưng không đồng bộ với những gì mình đã làm với compiler của GNU). Mình biết sử dụng MinGW, Cygwin và các công cụ của chúng.
Thật lạ lùng là cái Palm Dev Suite free hoàn toàn sử dụng Cygwin cùng với Eclipse, vậy mà bộ Palm OS CDK lại chỉ hỗ trợ MSVC. Mình có cảm giác như không làm được vậy, đã search nhiều trên Google nhưng không thấy cái bài nào hướng dẫn cụ thể cả mặc dù thấy có nhiều người làm được, nhưng họ không hướng dẫn đầy đủ (ví dụ http://news.palmos.com/read/messages?id=172118 ).
Vấn đề nảy sinh là do những .lib cung cấp bởi Palm là của MSVC (cách name mangling khác với GNU), vì vậy mình đã cố gắng chuyển những .lib này về .a (theo hướng dẫn của MingGW tại đây http://www.mingw.org/mingwfaq.shtml#faq-msvcdll).
Sau đó compile vẫn không link được hàm gọi của CondMgr.dll, nó cứ tìm kiếm cái function với cách name mangling khá lạ lùng do vậy nên báo lỗi:
Undefined reference to '_Z26CmConvertStringToCreatorIDPKcPm@8'
Kiểu name mangling này không biết là của GNU hay MSVC vậy nữa???
Đây là code conduit đơn giản (gần như không làm gì, chỉ dùng để test khả năng link với CondMgr.dll)
Thật lạ lùng là cái Palm Dev Suite free hoàn toàn sử dụng Cygwin cùng với Eclipse, vậy mà bộ Palm OS CDK lại chỉ hỗ trợ MSVC. Mình có cảm giác như không làm được vậy, đã search nhiều trên Google nhưng không thấy cái bài nào hướng dẫn cụ thể cả mặc dù thấy có nhiều người làm được, nhưng họ không hướng dẫn đầy đủ (ví dụ http://news.palmos.com/read/messages?id=172118 ).
Vấn đề nảy sinh là do những .lib cung cấp bởi Palm là của MSVC (cách name mangling khác với GNU), vì vậy mình đã cố gắng chuyển những .lib này về .a (theo hướng dẫn của MingGW tại đây http://www.mingw.org/mingwfaq.shtml#faq-msvcdll).
Sau đó compile vẫn không link được hàm gọi của CondMgr.dll, nó cứ tìm kiếm cái function với cách name mangling khá lạ lùng do vậy nên báo lỗi:
Undefined reference to '_Z26CmConvertStringToCreatorIDPKcPm@8'
Kiểu name mangling này không biết là của GNU hay MSVC vậy nữa???
Đây là code conduit đơn giản (gần như không làm gì, chỉ dùng để test khả năng link với CondMgr.dll)
////////////////////////////////////////////////
// Blank C++ Palm Conduit Project For Dev-C++
// Mono language support
// Author : d2c
// Idea : GenCond.vprj (Palm Conduit SDK)
//
// Palm Conduit SDK : 6.0
// Dev-C++ : 4.9.9.2 (5.0 beta)
//
// File : dllmain.cpp
////////////////////////////////////////////////
// Windows system includes
#include <windows.h>
#include <cstring>
#include <cstdio>
// HotSync includes
#include <CondAPI.h>
#include <SyncAPI.h>
#include <CondMgr.h>
#include <PALM_CMN.H>
// DLL header includes
#include "dll.h"
#include "resource.h"
// Global variable
HANDLE myInst;
extern HANDLE myInst;
/////////////////GetConduitInfo()/////////////
//
// Conduit entry point
// Get meta information about the conduit
//
// Check pInArgs
// Put data out in pOut and set pdwOutSize
//
///////////////////////////////////////////
COND_API SInt32 GetConduitInfo(ConduitInfoEnum infoType, void* pInArgs, void* pOut, DWORD* pdwOutSize)
{
if (!pOut)
return CONDERR_INVALID_PTR;
if (!pdwOutSize)
return CONDERR_INVALID_OUTSIZE_PTR;
switch (infoType) {
// <=> GetConduitName
case eConduitName:
if (!pInArgs) {
return CONDERR_INVALID_INARGS_PTR;
}
ConduitRequestInfoType *pInfo;
pInfo = (ConduitRequestInfoType *)pInArgs;
if ((pInfo->dwVersion != CONDUITREQUESTINFO_VERSION_1) ||
(pInfo->dwSize != SZ_CONDUITREQUESTINFO)) {
return CONDERR_INVALID_INARGS_STRUCT;
}
// all are ok put data to pOut
// and set pdwOutSize
std::strcpy((char *)pOut, MY_CONDUIT_NAME);
*pdwOutSize = std::strlen((char *)pOut);
break;
// Default action if synchonize method is not defined
case eDefaultAction:
break;
// Return conduit registration
case eRegistrationInfo:
if (*pdwOutSize != sizeof(RegistrationInfoType)) {
return CONDERR_INVALID_BUFFER_SIZE;
}
RegistrationInfoType* sRIT;
sRIT = (RegistrationInfoType*) pOut;
DWORD dwCreatorID;
int iError;
iError = CmConvertStringToCreatorID(MY_CONDUIT_CREATORID, &dwCreatorID);
sRIT->dwCreatorID = dwCreatorID;
sRIT->dwPriority = MY_CONDUIT_PRIORITY;
std::strcpy(sRIT->szLocalDirectory, MY_CONDUIT_DIRECTORY);
std::strcpy(sRIT->szLocalFile, MY_CONDUIT_FILE);
std::strcpy(sRIT->szRemoteDB, MY_CONDUIT_REMOTEDB);
std::strcpy(sRIT->szTitle, MY_CONDUIT_NAME);
break;
// Run it always?
case eRunAlways:
if (*pdwOutSize != sizeof(SInt8)) {
return CONDERR_INVALID_BUFFER_SIZE;
}
// 1 always run
*(SInt8*)pOut = 1;
break;
case eDoNotDisplayProgress:
if (*pdwOutSize != sizeof(SInt8)) {
return CONDERR_INVALID_BUFFER_SIZE;
}
// don't opt out of progress dialog
*(SInt8*)pOut = 0;
break;
case eDoNotDisplayInConduitListForUser:
if (!pInArgs) {
return CONDERR_INVALID_INARGS_PTR;
}
if (*pdwOutSize != sizeof(SInt8)) {
return CONDERR_INVALID_BUFFER_SIZE;
}
// ConduitRequestInfoType* pInfo = (ConduitRequestInfoType*) pInArgs;
// make decision to display conduit in Custom list for particular pInfo->szUser
*(SInt8*)pOut = 0;
break;
default:
return CONDERR_UNSUPPORTED_CONDUITINFO_ENUM;
}
return 0;
}
/////////////////GetConduitVersion()//////////
//
// Conduit entry point
// Get the conduit version
//
// return format 00 00 [v] [sv]
// v = version
// sv = sub version
//
///////////////////////////////////////////
COND_API UInt32 GetConduitVersion()
{
return MY_CONDUIT_VERSION;
}
/////////////////GetConduitName()//////////
//
// Conduit entry point
// Get the conduit name
//
// load conduit name in pszName
// (nLen is the max size of pszName)
// return 0 to tell successfully executed
// -1 in other cases
//
///////////////////////////////////////////
COND_API SInt32 GetConduitName(char* pszName,WORD nLen)
{
long retval = -1;
if (nLen<std::strlen(MY_CONDUIT_NAME)) {
std::strcpy(pszName, MY_CONDUIT_NAME);
return 0;
}
return retval; // failed
}
////////////////OpenConduit()//////////////
//
// Conduit main entry point
// Synchonize flow control
//
///////////////////////////////////////////
COND_API SInt32 OpenConduit(PROGRESSFN pFn, CSyncProperties& rProps)
{
long retval = -1;
if (pFn) {
// Synchronize flow
}
return retval;
}
///////////////DllMain()///////////////////
//
// DLL main entry point
// Load environment and loading variables
//
///////////////////////////////////////////
extern "C" bool APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
myInst = hInstance;
// others variable?
}
else if (dwReason == DLL_PROCESS_DETACH)
{
// unload..
}
return true;
}