Le forum (ô combien francophone) des utilisateurs de Powerbuilder.
Bonjour, je suis en train de développer une extension visuelle pour powerbuilder (censée gérer une webcam) en C++.
Je suis tombé sur 3 problèmes:
_ une API C++ PB archaïque ( il faut créer pas loin de 6-7 fonctions différentes sans compter la classe qui doit accomplir le rôle que l'on veut )
_ un manque flagrant de documentation sur la gestion des évènements.
_ un autre manque de documentation sur l'utilisation de certains paramètres qui sont passés aux fonctions/méthodes C++.
Pour pallier au 1er point, j'ai codé un système C++ (à base de template, d'héritage, callback & cie) qui me permet de n'avoir qu'a hériter d'une classe précise, déclarer quelles méthodes de celle-ci seront utilisées par powerbuilder dans son constructeur et ajouter dans une fonctions (pas membre, une bonne vieille fonction globale à la C, dont j'ai imposé le nom dans mon système) la ligne qui permet d'enregistrer la classe en question dans mon mécanisme. (le résultat est que cela me prend exactement 2+N lignes de codes a ajouter pour se faire supporter par PB: 2: déclaration de l'héritage, enregistrement de la classe, et N=nombre de méthodes accessibles par PB, et une interface qui sera simple a réutiliser pour mes collègues)
Enfin, tout ça, c'est ce que mon système est censé faire.
Dans la pratique, et en l'état actuel, une classe sans méthode partagée ("event", "function", "subroutine") fonctionne (dans l'application que je dois faire, l'image de la camera s'affiche bel et bien. Cela signifie que le constructeur et la méthode qui gère les évènements windows sont bien appelées).
Mais je suis en butte a un problème pour les méthodes partagées, à cause de la difficulté à trouver de la documentation sur certains paramètres dont je ne saisis pas le rôle.
Dans la doc que j'ai trouvée, la seul chose qui soit a peu près convenablement expliqué sont les extensions non visuelles. Les plus simples... ( ceci dis, je n'ai pas regardé le passage sur le marshaling vu qu'il ne me concerne pas pour le moment)
L'usage de la structure PBCallInfo et de l'énumération(?) pbmethodID sont les seules choses réellement documentée.
Je n'ai encore rien trouvé au sujet des structures/classes suivantes: "pbobject" et "IPB_Session".
Je les aurais bien passés tels quels a mes callbacks, sauf qu'utilisant des pointeurs sur fonctions membres, c'est un chouïa plus compliqué. Je n'ai pas trop envie de réinventer les foncteurs (aka fonctions objets), et ceux de la STL C++ ne permettent l'utilisation que d'un argument. Chose qui peut être contournée avec certaines fonctions (toujours STL) qui lient de façon statique un argument au foncteur. Mais voila, comme je ne sais pas du tout ce que sont ces satanés paramètres, je ne peux pas me permettre de les lier statiquement...
Donc voila, si quelqu'un a déjà manipulé ces objets, s'il a de la doc dessus, ou des exemples, je suis preneur.
[edit] petite correction [/edit]
[edit2] copier/coller des déclarations dans les headers de l'API de PB
struct _pbobject {}; typedef struct _pbobject *pbobject; //**************************************************************************** // IPB_Session //**************************************************************************** struct IPB_Session { virtual void Release() = 0; virtual pbclass GetClass(pbobject obj) = 0; virtual pbgroup GetSystemGroup() = 0; virtual pbmethodID GetMethodID(pbclass cls, LPCTSTR methodName, PBRoutineType rt, LPCTSTR signature, pbboolean publicOnly = true) = 0; virtual pbmethodID FindMatchingFunction(pbclass cls, LPCTSTR methodName, PBRoutineType rt, LPCTSTR readableSignature) = 0; virtual pbmethodID GetMethodIDByEventID(pbclass cls, LPCTSTR eventID) = 0; virtual PBXRESULT InitCallInfo(pbclass cls, pbmethodID mid, PBCallInfo *ci) = 0; virtual void FreeCallInfo(PBCallInfo *ci) = 0; virtual void AddLocalRef(pbobject obj) = 0; virtual void RemoveLocalRef(pbobject obj) = 0; virtual void AddGlobalRef(pbobject obj) = 0; virtual void RemoveGlobalRef(pbobject obj) = 0; virtual void PushLocalFrame() = 0; virtual void PopLocalFrame() = 0; // For passing variable arguments. virtual PBXRESULT AddIntArgument(PBCallInfo *ci, pbint value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddLongArgument(PBCallInfo *ci, pblong value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddRealArgument(PBCallInfo *ci, pbreal value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddDoubleArgument(PBCallInfo *ci, pbdouble value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddDecArgument(PBCallInfo *ci, pbdec value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddPBStringArgument(PBCallInfo *ci, pbstring value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddStringArgument(PBCallInfo *ci, LPCTSTR value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddBoolArgument(PBCallInfo *ci, pbboolean value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddUintArgument(PBCallInfo *ci, pbuint value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddUlongArgument(PBCallInfo *ci, pbulong value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddBlobArgument(PBCallInfo *ci, pbblob value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddDateArgument(PBCallInfo *ci, pbdate value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddTimeArgument(PBCallInfo *ci, pbtime value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddDateTimeArgument(PBCallInfo *ci, pbdatetime value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddCharArgument(PBCallInfo *ci, pbchar value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddLongLongArgument(PBCallInfo *ci, pblonglong value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddObjectArgument(PBCallInfo *ci, pbobject value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT AddArrayArgument(PBCallInfo *ci, pbarray value, pbboolean isNull=FALSE) = 0; virtual PBXRESULT InvokeClassFunction(pbclass cls, pbmethodID mid, PBCallInfo *ci) = 0; virtual PBXRESULT InvokeObjectFunction(pbobject obj, pbmethodID mid, PBCallInfo *ci) = 0; virtual PBXRESULT TriggerEvent(pbobject obj, pbmethodID mid, PBCallInfo *ci) = 0; virtual pbboolean HasExceptionThrown() = 0; virtual pbobject GetException() = 0; virtual void ClearException() = 0; virtual void ThrowException(pbobject ex) = 0; virtual pbgroup GetCurrGroup() = 0; virtual pbgroup FindGroup(LPCTSTR name, pbgroup_type) = 0; virtual pbclass FindClass(pbgroup group, LPCTSTR name) = 0; virtual pbclass FindClassByClassID(pbgroup group, pbint classID) = 0; virtual LPCTSTR GetClassName(pbclass cls) = 0; virtual pbclass GetSuperClass(pbclass cls) = 0; virtual pbclass GetSystemClass(pbclass cls) = 0; virtual pbboolean IsAutoInstantiate(pbclass pbcls) = 0; virtual pbobject NewObject(pbclass cls) = 0; virtual pbfieldID GetFieldID(pbclass cls, LPCTSTR fieldName) = 0; virtual pbuint GetFieldType(pbclass, pbfieldID) = 0; virtual pbulong GetNumOfFields(pbclass) = 0; virtual LPCTSTR GetFieldName(pbclass, pbfieldID) = 0; virtual pbboolean IsFieldNull(pbobject, pbfieldID) = 0; virtual void SetFieldToNull(pbobject, pbfieldID) = 0; virtual pbboolean IsFieldArray(pbclass, pbfieldID) = 0; virtual pbboolean IsFieldObject(pbclass, pbfieldID) = 0; virtual PBXRESULT UpdateField(pbobject obj, pbfieldID fid) = 0; virtual pbint GetIntField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pblong GetLongField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbreal GetRealField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdouble GetDoubleField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdec GetDecField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbstring GetStringField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbboolean GetBoolField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbuint GetUintField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbulong GetUlongField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbblob GetBlobField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdate GetDateField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbtime GetTimeField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdatetime GetDateTimeField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbchar GetCharField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pblonglong GetLongLongField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbobject GetObjectField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual pbarray GetArrayField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual PBXRESULT SetIntField(pbobject obj, pbfieldID fid, pbint value) = 0; virtual PBXRESULT SetLongField(pbobject obj, pbfieldID fid, pblong value) = 0; virtual PBXRESULT SetRealField(pbobject obj, pbfieldID fid, pbreal value) = 0; virtual PBXRESULT SetDoubleField(pbobject obj, pbfieldID fid, pbdouble value) = 0; virtual PBXRESULT SetDecField(pbobject obj, pbfieldID fid, pbdec value) = 0; virtual PBXRESULT SetPBStringField(pbobject obj, pbfieldID fid, pbstring value) = 0; virtual PBXRESULT SetStringField(pbobject obj, pbfieldID fid, LPCTSTR value) = 0; virtual PBXRESULT SetBoolField(pbobject obj, pbfieldID fid, pbboolean value) = 0; virtual PBXRESULT SetUintField(pbobject obj, pbfieldID fid, pbuint value) = 0; virtual PBXRESULT SetUlongField(pbobject obj, pbfieldID fid, pbulong value) = 0; virtual PBXRESULT SetBlobField(pbobject obj, pbfieldID fid, pbblob value) = 0; virtual PBXRESULT SetDateField(pbobject obj, pbfieldID fid, pbdate value) = 0; virtual PBXRESULT SetTimeField(pbobject obj, pbfieldID fid, pbtime value) = 0; virtual PBXRESULT SetDateTimeField(pbobject obj, pbfieldID fid, pbdatetime value) = 0; virtual PBXRESULT SetCharField(pbobject obj, pbfieldID fid, pbchar value) = 0; virtual PBXRESULT SetLongLongField(pbobject obj, pbfieldID fid, pblonglong value) = 0; virtual PBXRESULT SetObjectField(pbobject obj, pbfieldID fid, pbobject value) = 0; virtual PBXRESULT SetArrayField(pbobject obj, pbfieldID fid, pbarray value) = 0; virtual pbfieldID GetSharedVarID(pbgroup group, LPCTSTR fieldName) = 0; virtual pbuint GetSharedVarType(pbgroup, pbfieldID) = 0; virtual pbboolean IsSharedVarNull(pbgroup, pbfieldID) = 0; virtual void SetSharedVarToNull(pbgroup, pbfieldID) = 0; virtual pbboolean IsSharedVarArray(pbgroup, pbfieldID) = 0; virtual pbboolean IsSharedVarObject(pbgroup, pbfieldID) = 0; virtual pbint GetIntSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pblong GetLongSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbreal GetRealSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdouble GetDoubleSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdec GetDecSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbstring GetStringSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbboolean GetBoolSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbuint GetUintSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbulong GetUlongSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbblob GetBlobSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdate GetDateSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbtime GetTimeSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbdatetime GetDateTimeSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbchar GetCharSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pblonglong GetLongLongSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbobject GetObjectSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual pbarray GetArraySharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual PBXRESULT SetIntSharedVar(pbgroup group, pbfieldID fid, pbint value) = 0; virtual PBXRESULT SetLongSharedVar(pbgroup group, pbfieldID fid, pblong value) = 0; virtual PBXRESULT SetRealSharedVar(pbgroup group, pbfieldID fid, pbreal value) = 0; virtual PBXRESULT SetDoubleSharedVar(pbgroup group, pbfieldID fid, pbdouble value) = 0; virtual PBXRESULT SetDecSharedVar(pbgroup group, pbfieldID fid, pbdec value) = 0; virtual PBXRESULT SetPBStringSharedVar(pbgroup group, pbfieldID fid, pbstring value) = 0; virtual PBXRESULT SetStringSharedVar(pbgroup group, pbfieldID fid, LPCTSTR value) = 0; virtual PBXRESULT SetBoolSharedVar(pbgroup group, pbfieldID fid, pbboolean value) = 0; virtual PBXRESULT SetUintSharedVar(pbgroup group, pbfieldID fid, pbuint value) = 0; virtual PBXRESULT SetUlongSharedVar(pbgroup group, pbfieldID fid, pbulong value) = 0; virtual PBXRESULT SetBlobSharedVar(pbgroup group, pbfieldID fid, pbblob value) = 0; virtual PBXRESULT SetDateSharedVar(pbgroup group, pbfieldID fid, pbdate value) = 0; virtual PBXRESULT SetTimeSharedVar(pbgroup group, pbfieldID fid, pbtime value) = 0; virtual PBXRESULT SetDateTimeSharedVar(pbgroup group, pbfieldID fid, pbdatetime value) = 0; virtual PBXRESULT SetCharSharedVar(pbgroup group, pbfieldID fid, pbchar value) = 0; virtual PBXRESULT SetLongLongSharedVar(pbgroup group, pbfieldID fid, pblonglong value) = 0; virtual PBXRESULT SetObjectSharedVar(pbgroup group, pbfieldID fid, pbobject value) = 0; virtual PBXRESULT SetArraySharedVar(pbgroup group, pbfieldID fid, pbarray value) = 0; virtual pbfieldID GetGlobalVarID(LPCTSTR varName) = 0; virtual pbuint GetGlobalVarType(pbfieldID) = 0; virtual pbboolean IsGlobalVarNull(pbfieldID) = 0; virtual void SetGlobalVarToNull(pbfieldID) = 0; virtual pbboolean IsGlobalVarArray(pbfieldID) = 0; virtual pbboolean IsGlobalVarObject(pbfieldID) = 0; virtual pbint GetIntGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pblong GetLongGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbreal GetRealGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbdouble GetDoubleGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbdec GetDecGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbstring GetStringGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbboolean GetBoolGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbuint GetUintGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbulong GetUlongGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbblob GetBlobGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbdate GetDateGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbtime GetTimeGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbdatetime GetDateTimeGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbchar GetCharGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pblonglong GetLongLongGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbobject GetObjectGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual pbarray GetArrayGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual PBXRESULT SetIntGlobalVar(pbfieldID fid, pbint value) = 0; virtual PBXRESULT SetLongGlobalVar(pbfieldID fid, pblong value) = 0; virtual PBXRESULT SetRealGlobalVar(pbfieldID fid, pbreal value) = 0; virtual PBXRESULT SetDoubleGlobalVar(pbfieldID fid, pbdouble value) = 0; virtual PBXRESULT SetDecGlobalVar(pbfieldID fid, pbdec value) = 0; virtual PBXRESULT SetPBStringGlobalVar(pbfieldID fid, pbstring value) = 0; virtual PBXRESULT SetStringGlobalVar(pbfieldID fid, LPCTSTR value) = 0; virtual PBXRESULT SetBoolGlobalVar(pbfieldID fid, pbboolean value) = 0; virtual PBXRESULT SetUintGlobalVar(pbfieldID fid, pbuint value) = 0; virtual PBXRESULT SetUlongGlobalVar(pbfieldID fid, pbulong value) = 0; virtual PBXRESULT SetBlobGlobalVar(pbfieldID fid, pbblob value) = 0; virtual PBXRESULT SetDateGlobalVar(pbfieldID fid, pbdate value) = 0; virtual PBXRESULT SetTimeGlobalVar(pbfieldID fid, pbtime value) = 0; virtual PBXRESULT SetDateTimeGlobalVar(pbfieldID fid, pbdatetime value) = 0; virtual PBXRESULT SetCharGlobalVar(pbfieldID fid, pbchar value) = 0; virtual PBXRESULT SetLongLongGlobalVar(pbfieldID fid, pblonglong value) = 0; virtual PBXRESULT SetObjectGlobalVar(pbfieldID fid, pbobject value) = 0; virtual PBXRESULT SetArrayGlobalVar(pbfieldID fid, pbarray value) = 0; virtual pbboolean IsNativeObject(pbobject obj) = 0; virtual IPBX_UserObject* GetNativeInterface(pbobject obj) = 0; //Interface to access Array virtual pbarray NewBoundedSimpleArray(pbuint type, pbuint dimensions, PBArrayInfo::ArrayBound* bounds) = 0; //bounded array are fixed size, can be multidimension virtual pbarray NewUnboundedSimpleArray(pbuint type) = 0; //unbounded array are variable size, can only 1 dimension virtual pbarray NewBoundedObjectArray(pbclass, pbuint dimensions, PBArrayInfo::ArrayBound* bounds) = 0; //bounded array are fixed size, can be multidimension virtual pbarray NewUnboundedObjectArray(pbclass) = 0; //unbounded array are variable size, can only 1 dimension virtual pblong GetArrayLength(pbarray) = 0; virtual PBArrayInfo* GetArrayInfo(pbarray) = 0; virtual PBXRESULT ReleaseArrayInfo(PBArrayInfo*) = 0; // Release info, if and only if the memory is allocated from pb virtual pbboolean IsArrayItemNull(pbarray array, pblong dim[]) = 0; virtual void SetArrayItemToNull(pbarray array, pblong dim[] ) = 0; virtual pbuint GetArrayItemType(pbarray array, pblong dim[] ) = 0; virtual pbint GetIntArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pblong GetLongArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbreal GetRealArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbdouble GetDoubleArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbdec GetDecArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbstring GetStringArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbboolean GetBoolArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbuint GetUintArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbulong GetUlongArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbblob GetBlobArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbdate GetDateArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbtime GetTimeArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbdatetime GetDateTimeArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbchar GetCharArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pblonglong GetLongLongArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbobject GetObjectArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual PBXRESULT SetIntArrayItem(pbarray array, pblong dim[], pbint) = 0; virtual PBXRESULT SetLongArrayItem(pbarray array, pblong dim[], pblong) = 0; virtual PBXRESULT SetRealArrayItem(pbarray array, pblong dim[], pbreal) = 0; virtual PBXRESULT SetDoubleArrayItem(pbarray array, pblong dim[], pbdouble) = 0; virtual PBXRESULT SetDecArrayItem(pbarray array, pblong dim[], pbdec) = 0; virtual PBXRESULT SetPBStringArrayItem(pbarray array, pblong dim[], pbstring) = 0; virtual PBXRESULT SetStringArrayItem(pbarray array, pblong dim[], LPCTSTR) = 0; virtual PBXRESULT SetBoolArrayItem(pbarray array, pblong dim[], pbboolean) = 0; virtual PBXRESULT SetUintArrayItem(pbarray array, pblong dim[], pbuint) = 0; virtual PBXRESULT SetUlongArrayItem(pbarray array, pblong dim[], pbulong) = 0; virtual PBXRESULT SetBlobArrayItem(pbarray array, pblong dim[], pbblob) = 0; virtual PBXRESULT SetDateArrayItem(pbarray array, pblong dim[], pbdate) = 0; virtual PBXRESULT SetTimeArrayItem(pbarray array, pblong dim[], pbtime) = 0; virtual PBXRESULT SetDateTimeArrayItem(pbarray array, pblong dim[], pbdatetime) = 0; virtual PBXRESULT SetCharArrayItem(pbarray array, pblong dim[], pbchar) = 0; virtual PBXRESULT SetLongLongArrayItem(pbarray array, pblong dim[], pblonglong) = 0; virtual PBXRESULT SetObjectArrayItem(pbarray array, pblong dim[], pbobject) = 0; //Interface to access String. virtual pbstring NewString(LPCTSTR) = 0; virtual PBXRESULT SetString(pbstring, LPCTSTR) = 0; virtual pblong GetStringLength(pbstring pbstr) = 0; virtual LPCTSTR GetString(pbstring pbstr) = 0;//only return the pointer to LPTSTR, don't dup string //Interface to access Binary. virtual pbblob NewBlob(const void* bin, pblong len) = 0; //dup the binary virtual PBXRESULT SetBlob(pbblob, const void* bin, pblong len) = 0; //dup the binary virtual pblong GetBlobLength(pbblob pbbin) = 0; virtual void* GetBlob(pbblob pbbin) = 0;//only return the pointer to void, don't dup buffer //Interface to access Date, Time and DateTime. virtual pbdate NewDate() = 0; virtual pbtime NewTime() = 0; virtual pbdatetime NewDateTime() = 0; virtual PBXRESULT SetDate(pbdate date, pbint year, pbint month, pbint day) = 0; virtual PBXRESULT SetTime(pbtime time, pbint hour, pbint minute, pbdouble second) = 0; virtual PBXRESULT SetDateTime(pbdatetime dt, pbint year, pbint month, pbint day, pbint hour, pbint minute, pbdouble second) = 0; virtual PBXRESULT CopyDateTime(pbdatetime dest, pbdatetime src) = 0; //Copy memory virtual PBXRESULT SplitDate(pbdate date, pbint *year, pbint *month, pbint *day) = 0; virtual PBXRESULT SplitTime(pbtime time, pbint *hour, pbint *minute, pbdouble *second) = 0; virtual PBXRESULT SplitDateTime(pbdatetime dt, pbint *year, pbint *month, pbint *day, pbint *hour, pbint *minute, pbdouble *second) = 0; virtual LPCTSTR GetDateString(pbdate) = 0; virtual void ReleaseDateString(LPCTSTR) = 0; virtual LPCTSTR GetTimeString(pbtime) = 0; virtual void ReleaseTimeString(LPCTSTR) = 0; virtual LPCTSTR GetDateTimeString(pbdatetime) = 0; virtual void ReleaseDateTimeString(LPCTSTR) = 0; //interface to access decimal number virtual pbdec NewDecimal() = 0; virtual PBXRESULT SetDecimal(pbdec dec, LPCTSTR dec_str) = 0; virtual LPCTSTR GetDecimalString(pbdec) = 0; virtual void ReleaseDecimalString(LPCTSTR) = 0; virtual pbproxyObject NewProxyObject(pbclass cls) = 0; virtual PBXRESULT SetMarshaler(pbproxyObject obj, IPBX_Marshaler* marshaler) = 0; virtual IPBX_Marshaler* GetMarshaler(pbproxyObject obj) = 0; virtual IPB_Value* AcquireValue(IPB_Value* value) = 0; virtual IPB_Value* AcquireArrayItemValue(pbarray arr, pblong dim[])=0; virtual void SetValue(IPB_Value* dest, IPB_Value* src) = 0; virtual void SetArrayItemValue(pbarray arr, pblong dim[], IPB_Value* src) = 0; virtual void ReleaseValue(IPB_Value* value) = 0; virtual void SetProp(LPCTSTR name, void* data) = 0; virtual void* GetProp(LPCTSTR name) = 0; virtual void RemoveProp(LPCTSTR name) = 0; virtual pbboolean ProcessPBMessage() = 0; virtual pblong GetEnumItemValue(LPCTSTR enumName, LPCTSTR enumItemName) = 0; virtual LPCTSTR GetEnumItemName(LPCTSTR enumName, pblong enumItemValue) = 0; virtual IPB_Value* GetPBAnyField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual IPB_Value* GetPBAnySharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual IPB_Value* GetPBAnyGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual IPB_Value* GetPBAnyArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual pbobject CreateResultSet(IPB_ResultSetAccessor* rs) = 0; virtual IPB_ResultSetAccessor* GetResultSetAccessor(pbobject rs) = 0; virtual void ReleaseResultSetAccessor(IPB_ResultSetAccessor* rs) = 0; virtual pbboolean RestartRequested() = 0; virtual pbboolean HasPBVisualObject() = 0; virtual void SetDebugTrace(LPCTSTR traceFile) = 0; //********************************************************** // Begin of the new type BYTE //********************************************************** virtual PBXRESULT AddByteArgument(PBCallInfo *ci, pbbyte value, pbboolean isNull=FALSE) = 0; virtual pbbyte GetByteField(pbobject obj, pbfieldID fid, pbboolean& isNull) = 0; virtual PBXRESULT SetByteField(pbobject obj, pbfieldID fid, pbbyte value) = 0; virtual pbbyte GetByteSharedVar(pbgroup group, pbfieldID fid, pbboolean& isNull) = 0; virtual PBXRESULT SetByteSharedVar(pbgroup group, pbfieldID fid, pbbyte value) = 0; virtual pbbyte GetByteGlobalVar(pbfieldID fid, pbboolean& isNull) = 0; virtual PBXRESULT SetByteGlobalVar(pbfieldID fid, pbbyte value) = 0; virtual pbbyte GetByteArrayItem(pbarray array, pblong dim[], pbboolean& isNull) = 0; virtual PBXRESULT SetByteArrayItem(pbarray array, pblong dim[], pbbyte) = 0; //********************************************************** // End of the new type BYTE //********************************************************** virtual void ReleaseString(LPCTSTR str) = 0; virtual PBXRESULT SetLargeUnboundedByteArrayItem(pbarray array, pblong dim[], pbbyte value,PBArrayInfo* arrinfo)=0; virtual void reserved2() = 0; virtual void reserved3() = 0; virtual void reserved4() = 0; virtual void reserved5() = 0; virtual void reserved6() = 0; virtual void reserved7() = 0; virtual void reserved8() = 0; virtual void reserved9() = 0; virtual void reserved10() = 0; protected: ~IPB_Session() {}; };
J'ai trouvé un petit truc qui explicite (au moins en partie) IPB_Session: http://infocenter.sybase.com/help/index … DJIHFJ.htm
Par contre, toujours rien sur le fameux pbobject...
[/edit2]
Dernière modification par bmorel (12-12-2011 14:21:09)
Hors ligne
Bonjour,
j'ai fait plusieurs extensions pour PB, notamment pour intégrer PCRE, libhashish et des conteneurs STL pour PB.
On en parle dans la section Tips à gogo, Sdk, Open source, partage de codes... du forum.
Mes extensions sont dispos (avec leur sources) sur ma page Free, ceci dit, je n'utilise quasi aucun évènement dans mes extensions, elle servent principalement à déclarer des classes avec des méthodes pour wrapper les différentes libs. Pour pbobject, tu auras peut-être quelques réponses dans le code de pbnihash ou de pbnilist car je m'en sers pour garder dans le code c++ des références vers des objets PB (pour les stocker dans une hashtable, liste ou vecteur).
Par ailleurs, xlat a commencé un projet perl2powerbuilder dans lequel il embarqué un interpréteur Perl pour PB. Lui par contre a beaucoup plus poussé son investigation sur l'API des PBNI, et il devrait pouvoir t'apporter de l'aide.
Dernière modification par seki (02-12-2011 11:04:01)
Hors ligne
pbobject : tu peux le considérer comme un handle qui permet d'accéder à un PowerObject via la classe IPB_Session.
Tu peux aussi regarder du côté de la doc :
- IPB_Session:: NewObject(pbclass cls)
- IPB_Session:: GetNativeInterface(pbobject obj)
IPB_Session : c'est l'interface entre ton code C++ PBNI et la PBVM, d'ailleurs si tu regardes l'interface IPB_VM, tu verras qu'elle propose deux méthodes chacune pour retourner un pointeur sur une IPB_Session.
Sinon il y a aussi des exemples de PBNI visuels chez sybase: CodeXchange
Hors ligne
La doc avait fait des référence a codeXchange, mais aucun lien ne semblait valide.
Si je comprend bien, IPB_Session ne contient que les fonctions vers les fonctions/méthodes que l'on utilise à l'intérieur de powerbuilder, tandis que pbobject contiens "les types", les objets powerbuilder?
Si c'est le cas, j'imagine que lorsque powerbuilder donne la main à une PBNI, le pbobject qu'il lui passe correspond à l'objet père?
En tout cas, merci pour vos tuyaux, je vais aller me renseigner sur les fonctions que xlat m'a indiqué.
Et surtout, je sais maintenant qu'il faut que je dois les transmettre aux objects fils et de quelle façon... y'a plus qu'a, comme on dis...
Pour les évènements je fouinerai, en attendant je peux les traiter dans PB, même si c'est moins propre... C'est surtout le comment rendre dynamique l'appel aux fonctions membres de l'extension qui m'intéresse dans un 1er temps. Et comprendre exactement ce qu'il se passe, j'ai jamais été fan de coder sans comprendre.
[edit]
pas de balise style "résolu" ? Zut...
Dernière modification par bmorel (02-12-2011 14:05:09)
Hors ligne
bmorel a écrit:
Pour les évènements je fouinerai, en attendant je peux les traiter dans PB, même si c'est moins propre... C'est surtout le comment rendre dynamique l'appel aux fonctions membres de l'extension qui m'intéresse dans un 1er temps. Et comprendre exactement ce qu'il se passe, j'ai jamais été fan de coder sans comprendre.
si tu peux m'expliquer ton besoin par l'exemple (pbni + powerscript) je pourrais peut-être t'en dire plus.
bmorel a écrit:
[edit]
pas de balise style "résolu" ? Zut...
Tu edites le titre de ton premier poste et tu ajoutes le fameux [RESOLU]
Hors ligne
Désolé pour le délai de réponse.
Pas bête pour le titre :D (en fait je voulais pas dire balise mais bouton... fatigue du vendredi ^^')
Pour le besoin, en gros, j'ai créé un système de classes et de templates C++ qui permet de créer une extension powerbuilder sans avoir a bidouiller les 4 fonctions et 3 méthodes différentes imposées par powerbuilder (bon, je dis des valeurs un peu au pif la, j'admet, je n'ai pas compté exactement) histoire de faciliter la maintenance (pouvoir faire le distingo entre le powerscript et la vraie mécanique de l'extension, et ne pas avoir a faire des allers-retours multiples entre les multiples fichiers à la moindre modif d'une classe. Après tout, une classe est censée être la seule à avoir la responsabilité de son contenu, en POO), en cas d'évolution ou tout simplement de débogage (ou de création d'une autre extension).
Mon problème était de savoir a quoi servent les données que powerbuilder file au programme, histoire de savoir si oui ou non elles étaient réellement utiles, et à quoi elles servent. (Pour le coup, j'ai fini par créer une structure qui contiens les 3)
L'obstacle que je dois maintenant résoudre (j'ai un peu de mal a avancer, je l'admet) est que dès lors qu'il y à un transfert de paramètres (en argument ou en retour, peu importe), l'extension crashe, sans que je ne sache trop pourquoi (message d'erreur pas franchement explicite à mes yeux, et je n'ai pas trouvé de moyen de débuguer une extension powerbuilder autrement qu'avec les archaïques impressions de texte à l'écran... enfin, dans un fichier, pour le coup)
Je crains de rencontrer plus tard un autre obstacle, lié à la finalité du projet actuel, qui sera de rafraîchir régulièrement la fenêtre afin que l'affichage d'un flux vidéo (une caméra pour le coup), très probablement à coup de timer. (Je suppose que je devrais réécrire l'event timer et utiliser le pointeur vers IPB_Session pour utiliser la méthode PB "timer(n)" mais j'aviserai quand j'en serai la)
Hors ligne
bmorel a écrit:
L'obstacle que je dois maintenant résoudre (j'ai un peu de mal a avancer, je l'admet) est que dès lors qu'il y à un transfert de paramètres (en argument ou en retour, peu importe), l'extension crashe, sans que je ne sache trop pourquoi (message d'erreur pas franchement explicite à mes yeux, et je n'ai pas trouvé de moyen de débuguer une extension powerbuilder autrement qu'avec les archaïques impressions de texte à l'écran... enfin, dans un fichier, pour le coup)
Pour debugger, il suffit de faire comme pour les dll avec visual studio :
- dans les paramètres du projet, dans la partie debug, il faut définir l'IDE PB comme étant l'application hôte à la ligne "Command" (on peut même charger le workspace en ligne de commande avec /workspace, p. ex /workspace worksp120.pbw dans l'option "Command Arguments")
- on met ses points d'arrêt où on veut
- on lance en mode debug => ça démarre L'IDE PB
- on démarre le projet PB
- quand l'exécution atteint le point d'arrêt on se retrouve à nouveau dans Visual Studio, et "y a pu ka"
Je crains de rencontrer plus tard un autre obstacle, lié à la finalité du projet actuel, qui sera de rafraîchir régulièrement la fenêtre afin que l'affichage d'un flux vidéo (une caméra pour le coup), très probablement à coup de timer. (Je suppose que je devrais réécrire l'event timer et utiliser le pointeur vers IPB_Session pour utiliser la méthode PB "timer(n)" mais j'aviserai quand j'en serai la)
Si c'est un objet visuel (owner drawn ?) pourquoi ne pas gérer directement le timer dans le code c++ ?
L'extension s'occupe toute seule de se rafraichir, pas besoin de faire le ping-pong avec PB. Surtout si c'est pour de la vidéo, ça risque de surcharger inutilement l'application lors du passage de PB au c++ et inversement. Il vaut mieux limiter au maximum les changements de contexte.
Dernière modification par seki (06-12-2011 16:26:50)
Hors ligne
Object visuel, oui, qui hérite de IPBX_VisualObject. Je ne sais pas ce que tu appelles "owner drawn"... La fenêtre qui contiens l'extension?
Gérer le timer dans powerbuilder m'embête pour deux raisons: celle que tu as citée, et le fait que je n'aime pas avoir à mettre du code relatif à une classe dans une autre. Une classe propre est quand même censée s'occuper d'elle-même toute seule.
Le souci, c'est que quand j'ai essayé dans le code C++ (mon 1er réflexe) de générer un timer, celui-ci semblait n'être jamais lancé, ou jamais attrapé, je ne sais pas trop. J'avais essayé avec les timer de windows, cela dis, pas avec celui de PB, peut-être que ce serait une solution, je vais essayer.
Bon, il faut dire que je ne suis pas familier du dev avec l'API windows, ni de visual studio et ses outils, je l'admet...
Et merci pour l'info concernant le debug, ça va grandement m'aider, ça fait bien longtemps que je n'ai plus recours aux impressions de texte pour déboguer, et si on se fait vite au confort des espions, points d'arrêts et affichage de pile, il est éprouvant de revenir en arrière...
Hors ligne
bmorel a écrit:
Et merci pour l'info concernant le debug, ça va grandement m'aider, ça fait bien longtemps que je n'ai plus recours aux impressions de texte pour déboguer, et si on se fait vite au confort des espions, points d'arrêts et affichage de pile, il est éprouvant de revenir en arrière...
Et que dire de la fonction "Edit and continue" à ce sujet !
Hors ligne
Par "edit and continue" tu veux dire modifier les variables, ou l'instruction à exécuter, ou le code lui-même? Si c'est le code lui-même, alors je ne savais pas que c'était possible.
Bon... alors en fait, mon problème pour passer des paramètres à mon extension powerbuilder était dû au tristement célèbre virus PEBCAK... J'ai supposé, je sais pas pourquoi, que PBNI utilisait le même premier index que powerbuilder: 1. Sauf que du coup, ben quand j'accédais à l'argument n°1, j'accédais au 2nd qui n'existait pas.
Me reste juste la question importante (bien que pas bloquante sur mon projet actuel) de pouvoir retourner une valeur.
Un code tel que:
"data.ci->returnValue->SetInt(v);"
cause un échec d'assertion dans la ligne 779.
Plus précisément: "Expression: vector subscript out of range"
Sinon, j'ai dû casser un truc, ce matin, après lecture du post sur le débug, les breakpoints marchaient, mais depuis midi, VS refuse de s'arrêter. Si quelqu'un à une idée, je suis preneur (je n'ai pourtant pas souvenir d'avoir modifier les paramètres du projet)
Hors ligne
bmorel a écrit:
Par "edit and continue" tu veux dire modifier les variables, ou l'instruction à exécuter, ou le code lui-même? Si c'est le code lui-même, alors je ne savais pas que c'était possible.
Oui, il faut mettre la bonne option au compilo (ou linker)
bmorel a écrit:
Me reste juste la question importante (bien que pas bloquante sur mon projet actuel) de pouvoir retourner une valeur.
Un code tel que:
"data.ci->returnValue->SetInt(v);"
cause un échec d'assertion dans la ligne 779.
Plus précisément: "Expression: vector subscript out of range"
Es-tu sure du type de returnValue ? ( data.ci->returnValue->GetType / IsArray / IsEnum / IsObject )
Normalement, çà doit correspondre à ce que tu déclares dans PBX_GetDescription.
bmorel a écrit:
Sinon, j'ai dû casser un truc, ce matin, après lecture du post sur le débug, les breakpoints marchaient, mais depuis midi, VS refuse de s'arrêter. Si quelqu'un à une idée, je suis preneur (je n'ai pourtant pas souvenir d'avoir modifier les paramètres du projet)
Des fois après modification de l'extension, il faut recompiler et puis regenerer le PBD (attention aux chemins relatifs/absolue vers le PBX; un coup d'oeil à l'éditeur Hexa pourra aider en cas de doute).
Ensuite copier les pbd/pbx dans le répertoire de ton projet PB de debuggage.
En général on fait çà dans un script PostBuild.
Sinon dès fois il faut aussi faire un full rebuild de l'extenion dans VS.
Hors ligne
xlat a écrit:
bmorel a écrit:
Par "edit and continue" tu veux dire modifier les variables, ou l'instruction à exécuter, ou le code lui-même? Si c'est le code lui-même, alors je ne savais pas que c'était possible.
Oui, il faut mettre la bonne option au compilo (ou linker)
Intéressant ça, je regarderai plus en détails un de ces 4, quand j'aurai suffisamment avancé sur le projet pour me permettre de partir à la découverte des fonctions avancées de ce compilateur la.
xlat a écrit:
bmorel a écrit:
Me reste juste la question importante (bien que pas bloquante sur mon projet actuel) de pouvoir retourner une valeur.
Un code tel que:
"data.ci->returnValue->SetInt(v);"
cause un échec d'assertion dans la ligne 779.
Plus précisément: "Expression: vector subscript out of range"Es-tu sure du type de returnValue ? ( data.ci->returnValue->GetType / IsArray / IsEnum / IsObject )
Normalement, çà doit correspondre à ce que tu déclares dans PBX_GetDescription.
Oui, ça correspond très précisément.
J'ai aussi tenté de passer un paramètre par référence, le crash est différent, mais ça reste un crash: "Error in reference argument passed in function/event call at line 7 in open event of object xxx"
En gros, récupérer les données ça passe, les écrire, ça crash.
xlat a écrit:
bmorel a écrit:
Sinon, j'ai dû casser un truc, ce matin, après lecture du post sur le débug, les breakpoints marchaient, mais depuis midi, VS refuse de s'arrêter. Si quelqu'un à une idée, je suis preneur (je n'ai pourtant pas souvenir d'avoir modifier les paramètres du projet)
Des fois après modification de l'extension, il faut recompiler et puis regenerer le PBD (attention aux chemins relatifs/absolue vers le PBX; un coup d'oeil à l'éditeur Hexa pourra aider en cas de doute).
Ensuite copier les pbd/pbx dans le répertoire de ton projet PB de debuggage.
En général on fait çà dans un script PostBuild.
Sinon dès fois il faut aussi faire un full rebuild de l'extenion dans VS.
Je viens d'essayer de fermer VS, nettoyer tous les fichiers non nécessaires à la compilation, et réouvrir VS, ça ne change rien. Méthode barbarre inefficace, je vais tenter la subtilité xD
Hors ligne