Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

В продолжение темы про DLL-классы на Delphi и MSVC. Нужен совет!


Страницы:   1 2

ПЗ ©   (2008-08-06 21:23:00) 

Имею плагин для 3d Studio MAX, написанный на С. Хочу написать его на Delphi. Плагин сидит в DLL, экспортирующей функцию, которая возвращает указатель на следующий класс (MessageBox вставлены мною для отладки):

// класс-описатель для вашего plug-in'а
class MyUtilityClassDesc
{
private:
 Tab  interfaces;  // the FnPub interfaces published by this plugin
           // maxutil.lib needed!

public:
 virtual void AAA() {}
 virtual void BBB() {}

 virtual ~MyUtilityClassDesc() {MessageBox(0,"ClassDesc.~ClassDesc","",MB_OK);}

 virtual int IsPublic()
 {
   MessageBox(0,"ClassDesc.IsPublic","",MB_OK);
   return 1;
 }

 virtual void * Create(BOOL loading = FALSE)
 {
   MessageBox(0,"ClassDesc.Create","",MB_OK);
   return NULL;//&theMyUtility;
 }
 int    BeginCreate(Interface *i) {MessageBox(0,"ClassDesc.BeginCreate","",MB_OK); return 0;}
 int    EndCreate(Interface *i) {MessageBox(0,"ClassDesc.EndCreate","",MB_OK); return 0;};

 virtual const TCHAR *  ClassName()
 {
   MessageBox(0,"ClassDesc.ClassName","",MB_OK);
   return "MyUtility";
 }

 virtual SClass_ID SuperClassID()
 {
  MessageBox(0,"ClassDesc.SuperClassID","",MB_OK);
  return UTILITY_CLASS_ID;
 }
 
 virtual CClassID ClassID()
 {
   MessageBox(0,"ClassDesc.ClassID","",MB_OK);
   return cid;//MYUTILITY_CLASS_ID;
 }

 virtual const TCHAR * Category()
 {
   MessageBox(0,"ClassDesc.Category","",MB_OK);
   return "Utility";
 }

  virtual BOOL   OkToCreate(Interface *i) {MessageBox(0,"ClassDesc.OkToCreate","",MB_OK); return TRUE; }
  virtual BOOL   HasClassParams() {MessageBox(0,"ClassDesc.HasClassParams","",MB_OK); return FALSE;}
  virtual void   EditClassParams(HWND hParent) {MessageBox(0,"ClassDesc.EditClassParams","",MB_OK);}
  virtual void   ResetClassParams(BOOL fileReset=FALSE) {MessageBox(0,"ClassDesc.ResetClassParams","",MB_OK);}
  virtual int          NumActionTables() {MessageBox(0,"ClassDesc.NumActionTables","",MB_OK); return 0; }
  virtual ActionTable*  GetActionTable(int i) {MessageBox(0,"ClassDesc.GetActionTable","",MB_OK); return NULL; }
  virtual BOOL IsManipulator() {MessageBox(0,"ClassDesc.IsManipulator","",MB_OK); return FALSE; }
  virtual BOOL CanManipulate(ReferenceTarget* hTarget) {MessageBox(0,"ClassDesc.CanManipulate","",MB_OK); return FALSE; }
  virtual BOOL CanManipulateNode(INode* pNode) {MessageBox(0,"ClassDesc.CanManipulateNode","",MB_OK); return FALSE; }
  virtual Manipulator* CreateManipulator(
    ReferenceTarget* hTarget,
    INode* pNode) {MessageBox(0,"ClassDesc.CreateManipulator","",MB_OK); return NULL; }
  virtual Manipulator* CreateManipulator(INode* pNode) {MessageBox(0,"ClassDesc.CreateManipulator2","",MB_OK); return NULL;}
  virtual BOOL   NeedsToSave() {MessageBox(0,"ClassDesc.NeedsToSave","",MB_OK); return FALSE; }
  virtual IOResult   Save(ISave *isave) {MessageBox(0,"ClassDesc.Save","",MB_OK); return IO_OK; }
  virtual IOResult   Load(ILoad *iload) {MessageBox(0,"ClassDesc.Load","",MB_OK); return IO_OK; }
  virtual DWORD   InitialRollupPageState()  {MessageBox(0,"ClassDesc.InitialRollupPageState","",MB_OK);  return 0x7fffffff;}

 // возвращает имя для MaxScript
 virtual const TCHAR * InternalName()
 {
   MessageBox(0,"ClassDesc.InternalName","",MB_OK);
   return _T("MyUtility");
 }

 // возвращает hInstance модуля
 virtual HINSTANCE HInstance()
 {
   MessageBox(0,"ClassDesc.HInstance","",MB_OK);
   return hInstance;
 }

 virtual int NumParamBlockDescs() {MessageBox(0,"ClassDesc.NumParamBlockDescs","",MB_OK); return 0; }
 virtual ParamBlockDesc2* GetParamBlockDesc(int i) {MessageBox(0,"ClassDesc.GetParamBlockDesc","",MB_OK); return NULL; }
 virtual ParamBlockDesc2* GetParamBlockDescByID(BlockID id) {MessageBox(0,"ClassDesc.GetParamBlockDescByID","",MB_OK); return NULL; }
 virtual void AddParamBlockDesc(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.AddParamBlockDesc","",MB_OK); }
 virtual void BeginEditParams(IObjParam *ip, ReferenceMaker* obj, ULONG flags, Animatable *prev) {MessageBox(0,"ClassDesc.BeginEditParams","",MB_OK); }
 virtual void EndEditParams(IObjParam *ip, ReferenceMaker* obj, ULONG flags, Animatable *prev) {MessageBox(0,"ClassDesc.EndEditParams","",MB_OK); }
 virtual void InvalidateUI(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.InvalidateUI","",MB_OK); }
 virtual MCHAR* GetRsrcString(INT_PTR id){MessageBox(0,"ClassDesc.GetRsrcString","",MB_OK); return NULL;};  
 virtual void MakeAutoParamBlocks(ReferenceMaker* owner) {MessageBox(0,"ClassDesc.MakeAutoParamBlocks","",MB_OK); }
 virtual int NumParamMaps() {MessageBox(0,"ClassDesc.NumParamMaps","",MB_OK); return 0; }
 virtual IParamMap2* GetParamMap(int i) {MessageBox(0,"ClassDesc.GetParamMap","",MB_OK); return NULL; }
 virtual IParamMap2* GetParamMap(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.GetParamMap2","",MB_OK); return NULL; }
 virtual void SetUserDlgProc(ParamBlockDesc2* pbd, ParamMap2UserDlgProc* proc=NULL) {MessageBox(0,"ClassDesc.SetUserDlgProc","",MB_OK); }
 virtual ParamMap2UserDlgProc* GetUserDlgProc(ParamBlockDesc2* pbd) {MessageBox(0,"ClassDesc.GetUserDlgProc","",MB_OK); return NULL; }
 virtual bool DrawRepresentation(COLORREF bkColor, HDC hDC, Rect &rect) {MessageBox(0,"ClassDesc.DrawRepresentation","",MB_OK); return FALSE; }
 virtual int NumInterfaces() {MessageBox(0,"ClassDesc.NumInterfaces","",MB_OK); return 0; }
 virtual FPInterface* GetInterfaceAt(int i) {MessageBox(0,"ClassDesc.GetInterfaceAt","",MB_OK); return NULL; }
 virtual FPInterface* GetInterface(Interface_ID id){MessageBox(0,"ClassDesc.GetInterface","",MB_OK); return NULL; }
 virtual FPInterface* GetInterface(MCHAR* name){MessageBox(0,"ClassDesc.GetInterface2","",MB_OK); return NULL; }
 virtual void AddInterface(FPInterface* fpi){MessageBox(0,"ClassDesc.AddInterface","",MB_OK); };
 virtual void ClearInterfaces() { MessageBox(0,"ClassDesc.ClearInterfaces","",MB_OK); }
 virtual Class_ID SubClassID() {MessageBox(0,"ClassDesc.SubClassID","",MB_OK); return Class_ID(); }
 virtual INT_PTR Execute(int cmd, ULONG_PTR arg1=0, ULONG_PTR arg2=0, ULONG_PTR arg3=0) {MessageBox(0,"ClassDesc.Execute","",MB_OK); return 0; }

};

Два виртуальных метода вначале - пустышки. Зачем нужны - ХЗ, но без них последовательность вызовов методов нарушается. Последовательность следующая:
1. MyUtilityClassDesc.SuperClassID()
2. MyUtilityClassDesc.ClassID()
3. MyUtilityClassDesc.SuperClassID()
4. MyUtilityClassDesc.IsPublic()
5. MyUtilityClassDesc.ClassID()
6. MyUtilityClassDesc.ClassName()
7. MyUtilityClassDesc.Category()
8. MyUtilityClassDesc.InitialPageRollupState()
9. MyUtilityClassDesc.NemActionTables()
....
Написал аналог на Delphi (cм. далее). Есть проблема, тебуется опытный глаз!


tesseract   (2008-08-06 22:32:00) [21]

Классы в DLL.... ИМХО там Com-server.


Сергей М.   (2008-08-06 21:58:00) [22]

С чего бы везде cdecl понатыкано ?
Не понятно ..
И вообще - есть же, наверно, документация по API для плагинов к этому продукту, почему бы ее не проштудировать, прежде чем лепить невесть что ?


ПЗ   (2008-08-06 21:28:00) [23]

//ClassDesc

destructor ClassDesc.ClassDesc();
begin
 inherited;
end;
function ClassDesc.IsPublic():integer;cdecl;  // Show this in create branch?
begin
 MessageBox(0,'IsPublic','ClassDesc',MB_OK);
 Result:=1;
end;
function ClassDesc.Creat(loading:Boolean=FALSE):Pointer;cdecl;   // return a pointer to an instance of the class.
begin
 MessageBox(0,'Creat','ClassDesc',MB_OK);

 Result:=nil;
end;
function ClassDesc.BeginCreate(i:IUnknown):Integer;cdecl; {return 0;}
begin
 MessageBox(0,'BeginCreate','ClassDesc',MB_OK);
 Result:=0;
end;
function ClassDesc.EndCreate(i:IUnknown):Integer;cdecl; {return 0;}
begin
 MessageBox(0,'EndCreate','ClassDesc',MB_OK);
 Result:=0;
end;
function ClassDesc.ClassName():PAnsiChar;cdecl;
begin
 MessageBox(0,'ClassName','ClassDesc',MB_OK);
 Result:=pchClassName;
 Result:=nil;
end;
function ClassDesc.SuperClassID():SClass_ID;cdecl;
begin
 MessageBox(0,'SuperClassID','ClassDesc',MB_OK);
 Result:=UTILITY_CLASS_ID;
end;
function ClassDesc.ClassID():TClass_ID;cdecl;
begin
 MessageBox(0,'ClassID','ClassDesc',MB_OK);
 Result:=c_id;
end;
function ClassDesc.Category():PAnsiChar;cdecl;   // primitive/spline/loft/ etc
begin
 MessageBox(0,'Category','ClassDesc',MB_OK);
 Result:=nil;
 Result:=pchCategory;
end;
function ClassDesc.OkToCreate(i:IUnknown):Boolean;cdecl; { return TRUE; } // return FALSE to disable create button
begin
 MessageBox(0,'OKCreate','ClassDesc',MB_OK);
 Result:=True;
end;
function ClassDesc.HasClassParams():Boolean;cdecl; {return FALSE;}
begin
 MessageBox(0,'HasClassParams','ClassDesc',MB_OK);
 Result:=False;
end;
procedure ClassDesc.EditClassParams(hParent:HWND);cdecl; {}
begin
 MessageBox(0,'EditClassParams','ClassDesc',MB_OK);
end;
procedure ClassDesc.ResetClassParams(fileReset:Boolean=FALSE);cdecl; {}
begin
 MessageBox(0,'ResetClassParams','ClassDesc',MB_OK);
end;
function ClassDesc.NumActionTables():Integer;cdecl; { return 0; }
begin
 MessageBox(0,'NewActTable','ClassDesc',MB_OK);
 Result:=0;
end;
function ClassDesc.GetActionTable(i:Integer):TActionTable;cdecl;  { return NULL; }
begin
 MessageBox(0,'GetActTable','ClassDesc',MB_OK);
 Result:=nil;
end;
function ClassDesc.IsManipulator():Boolean;cdecl; { return FALSE; }
begin
 MessageBox(0,'IsManip','ClassDesc',MB_OK);
 Result:=False;
end;
function ClassDesc.CanManipulate(hTarget:TReferenceTarget):Boolean;cdecl; { return FALSE; }
begin
 MessageBox(0,'CanManipulate','ClassDesc',MB_OK);
 Result:=False;
end;
function ClassDesc.CanManipulateNode(pNode:INode):Boolean;cdecl; { return FALSE; }
begin
 MessageBox(0,'CanManipulateNode','ClassDesc',MB_OK);
 Result:=False;
end;
function ClassDesc.CreateManipulator(hTarget:TReferenceTarget;pNode:INode):TManipulator;c decl; { return NULL; }
begin
 MessageBox(0,'CreateManipulator','ClassDesc',MB_OK);
 Result:=nil;
end;
function ClassDesc.CreateManipulator(pNode:INode):TManipulator;cdecl; {return NULL;}
begin
 MessageBox(0,'CreateManipulator','ClassDesc',MB_OK);
 Result:=nil;
end;
function ClassDesc.NeedsToSave():Boolean;cdecl; { return FALSE; }
begin
 MessageBox(0,'NeedsToSave','ClassDesc',MB_OK);
 Result:=False;
end;
function ClassDesc.Save(isave:ISave):TIOResult;cdecl; { return IO_OK; }
begin
 MessageBox(0,'Save','ClassDesc',MB_OK);
 result:=IO_OK;
end;
function ClassDesc.Load(iload:ILoad):TIOResult;cdecl; { return IO_OK; }
begin
 MessageBox(0,'Load','ClassDesc',MB_OK);
 result:=IO_OK;
end;
function ClassDesc.InitialRollupPageState():Longword;cdecl; { return 0x7fffffff; }
begin
 MessageBox(0,'InitialRollupPageState','ClassDesc',MB_OK);
 result:=$7fffffff;
end;

function ClassDesc.InternalName():PAnsiChar;cdecl; { return NULL; }
begin
 MessageBox(0,'IntName','ClassDesc',MB_OK);
 Result:=pchClassName;
end;
function ClassDesc.HInstance():Cardinal;cdecl; { return NULL; }
begin
 MessageBox(0,'hInstance','ClassDesc',MB_OK);
 Result:=hInstance;
end;
function ClassDesc.NumParamBlockDescs():Integer;cdecl; { return 0; }
begin
 MessageBox(0,'NumParamBlockDescs','ClassDesc',MB_OK);
 Result:=0;
end;
function ClassDesc.GetParamBlockDesc(i:Integer):TParamBlockDesc2;cdecl; { return NULL; }
begin
 MessageBox(0,'GetParamBlockDesc','ClassDesc',MB_OK);
 result:=nil;
end;
function ClassDesc.GetParamBlockDescByID(id:BlockID):TParamBlockDesc2;cdecl; { return NULL; }
begin
 MessageBox(0,'GetParamBlockDescByID','ClassDesc',MB_OK);
 result:=nil;
end;
procedure ClassDesc.AddParamBlockDesc(pbd:TParamBlockDesc2);cdecl; { }
begin
 MessageBox(0,'AddParamBlockDesc','ClassDesc',MB_OK);
end;
procedure ClassDesc.BeginEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);cdecl; { }
begin
 MessageBox(0,'BeginEditParams','ClassDesc',MB_OK);
end;
procedure ClassDesc.EndEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);cdecl; { }
begin
 MessageBox(0,'EndEditParams','ClassDesc',MB_OK);
end;
procedure ClassDesc.InvalidateUI(pbd:TParamBlockDesc2);cdecl; { }
begin
 MessageBox(0,'InvalidateUI','ClassDesc',MB_OK);
end;
function ClassDesc.GetRsrcString(id:INT_PTR):PAnsiChar;cdecl;
begin
 MessageBox(0,'GetRsrcStr','ClassDesc',MB_OK);
 Result:=nil;
end;
procedure ClassDesc.MakeAutoParamBlocks(owner:TReferenceMaker);cdecl; { }
begin
 MessageBox(0,'MakeAutoParamBlocks','ClassDesc',MB_OK);
end;
function ClassDesc.NumParamMaps():Integer;cdecl; { return 0; }
begin
 MessageBox(0,'NumParamMaps','ClassDesc',MB_OK);
 Result:=0;
end;
function ClassDesc.GetParamMap(i:Integer):IParamMap2;cdecl; { return NULL; }
begin
 MessageBox(0,'GetParamMap','ClassDesc',MB_OK);
 Result:=nil;
end;
function ClassDesc.GetParamMap(pbd:TParamBlockDesc2):IParamMap2;cdecl; { return NULL; }
begin
 MessageBox(0,'GetParamMap1','ClassDesc',MB_OK);
 Result:=nil;
end;
procedure ClassDesc.SetUserDlgProc(pbd:TParamBlockDesc2; proc:TParamMap2UserDlgProc=nil);cdecl; { }
begin
 MessageBox(0,'SetupDlgProc','ClassDesc',MB_OK);
end;
function ClassDesc.GetUserDlgProc(pbd:TParamBlockDesc2):TParamMap2UserDlgProc;cdecl; { return NULL; }
begin
 MessageBox(0,'GetUserDlgProc','ClassDesc',MB_OK);
 Result:=nil;
end;

...
...

function ClassDesc.SubClassID():TClass_ID;cdecl; { return Class_ID(); }
begin
 MessageBox(0,'SubClassId','ClassDesc',MB_OK);
 Result:=c_id;//self.ClassID();
end;
function ClassDesc.Execute(cmd:Integer; arg1:ULONG_PTR=0; arg2:ULONG_PTR=0; arg3:ULONG_PTR=0):INT_PTR;cdecl; { return 0; }
begin
 MessageBox(0,'Execute','ClassDesc',MB_OK);
 Result:=0;
end;


Все бы хорошо, но после вызова InitialPageRollupState происходит крэш! Как мне найти ошибку? Не наврал ли я с возвращением Pchar`ов и ClaccID()? Сам класс TClassID - простейший - два поля и несколько методов для доступа к ним. Если надо - приведу отдельно. Help!


ПЗ   (2008-08-06 21:25:00) [24]


ClassDesc=class {MaxHeapOperators}
private
 interfaces:Tab;
public
 destructor     ClassDesc();virtual;
 function IsPublic():integer;virtual;cdecl;  // Show this in create branch?
 function Creat(loading:Boolean=FALSE):Pointer;virtual;cdecl;   // return a pointer to an instance of the class.
 function BeginCreate(i:IUnknown):Integer;virtual;cdecl; {return 0;}
 function EndCreate(i:IUnknown):Integer;virtual;cdecl; {return 0;}
 function ClassName():PAnsiChar;virtual;cdecl;
 function SuperClassID():SClass_ID;virtual;cdecl;
 function ClassID():TClass_ID;virtual;cdecl;
 function Category():PAnsiChar;virtual;cdecl;   // primitive/spline/loft/ etc
 function OkToCreate(i:IUnknown):Boolean;virtual;cdecl; { return TRUE; } // return FALSE to disable create button
 function HasClassParams():Boolean;virtual;cdecl; {return FALSE;}
 procedure EditClassParams(hParent:HWND);virtual;cdecl; {}
 procedure ResetClassParams(fileReset:Boolean=FALSE);virtual;cdecl; {}
   function NumActionTables():Integer;virtual;cdecl; { return 0; }
 function GetActionTable(i:Integer):TActionTable;virtual;cdecl;  { return NULL; }
 function IsManipulator():Boolean;virtual;cdecl; { return FALSE; }
 function CanManipulate(hTarget:TReferenceTarget):Boolean;virtual;cdecl; { return FALSE; }
 function CanManipulateNode(pNode:INode):Boolean;virtual;cdecl; { return FALSE; }
 function CreateManipulator(hTarget:TReferenceTarget;pNode:INode):TManipulator;overload;vi rtual;cdecl; { return NULL; }
 function CreateManipulator(pNode:INode):TManipulator;overload;virtual;cdecl; {return NULL;}
 function NeedsToSave():Boolean;virtual;cdecl; { return FALSE; }
 function Save(isave:ISave):TIOResult;virtual;cdecl; { return IO_OK; }
 function Load(iload:ILoad):TIOResult;virtual;cdecl; { return IO_OK; }
 function InitialRollupPageState():DWord;virtual;cdecl; { return 0x7fffffff; }
 function InternalName():PAnsiChar;virtual;cdecl; { return NULL; }
 function HInstance():Cardinal;virtual;cdecl; { return NULL; }
 function NumParamBlockDescs():Integer;virtual;cdecl; { return 0; }
 function GetParamBlockDesc(i:Integer):TParamBlockDesc2;virtual;cdecl; { return NULL; }
 function GetParamBlockDescByID(id:BlockID):TParamBlockDesc2;virtual;cdecl; { return NULL; }
 procedure AddParamBlockDesc(pbd:TParamBlockDesc2);virtual;cdecl; { }
 procedure BeginEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);virtual;cdecl; { }
 procedure EndEditParams(ip:IObjParam; obj:TReferenceMaker; flags:Longword; prev:TAnimatable);virtual;cdecl; { }
 procedure InvalidateUI(pbd:TParamBlockDesc2);virtual;cdecl; { }
 {CoreExport} function GetRsrcString(id:INT_PTR):PAnsiChar;virtual;cdecl;
 procedure MakeAutoParamBlocks(owner:TReferenceMaker);virtual;cdecl; { }
 function NumParamMaps():Integer;virtual;cdecl; { return 0; }
 function GetParamMap(i:Integer):IParamMap2;overload;virtual;cdecl; { return NULL; }
 function GetParamMap(pbd:TParamBlockDesc2):IParamMap2;overload;virtual;cdecl; { return NULL; }
 procedure SetUserDlgProc(pbd:TParamBlockDesc2; proc:TParamMap2UserDlgProc=nil);virtual;cdecl; { }
 function GetUserDlgProc(pbd:TParamBlockDesc2):TParamMap2UserDlgProc;virtual;cdecl; { return NULL; }
 function DrawRepresentation(bkColor:COLORREF; DC:HDC; Rect:TRect):Boolean;virtual;cdecl; { return FALSE; }
 function NumInterfaces():integer;virtual;cdecl; { return interfaces.Count(); }
 function GetInterfaceAt(i:Integer):FPInterface;virtual;cdecl; { return interfaces[i]; }
 {CoreExport} function GetInterface(id:TInterface_ID):FPInterface;overload;virtual;cdecl;
 {CoreExport} function GetInterface(name:PAnsiChar):FPInterface;overload;virtual;cdecl;
 {CoreExport} procedure AddInterface(fpi:FPInterface);virtual;cdecl;
 procedure ClearInterfaces();virtual;cdecl; { interfaces.ZeroCount(); }
 function SubClassID():TClass_ID;virtual;cdecl; { return Class_ID(); }
 function Execute(cmd:Integer; arg1:ULONG_PTR=0; arg2:ULONG_PTR=0; arg3:ULONG_PTR=0):INT_PTR;virtual;cdecl; { return 0; }
end;

Реализацию сделал аналогично сишному аналогу, и тоже вставил MessageBox для контроля правильности вызовов методов. Здесь все вызывается правильно и никаких левых методов-пустышек не требуется (см. ниже).


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо