terminator said:
Is SelectedFORef castable to SOFORef ?(you have not declared the later
type.)
Really bad day for thinking yesterday.
Here's everything:
Mac OS X. XCode 2.4.
Here are the classes:
typedef class SelectedObject* SelectedObjectRef;
typedef SelectedObjectRef SORef;
typedef UInt32 SOOwnerID;
class SelectedObject {
UInt16 refCt;
SelObjectClass objectClass;
OSType ready;
protected:
SOOwnerID ID; // need to identify where the SO belongs. An SO in one
view will have
// different select flags to an SO in another view
SelObjectType objectType; // NYI
SelectionFlag selections;
static CFMutableSetRef soCache;
static void SOCacheSetProc(const void* value, void* ctx);
friend SORef CheckSOCache(SelObjectClass objClass, UInt16 objType,
SOOwnerID iID, void* data);
virtual OSStatus CheckCache(SelObjectClass objClass, UInt16 dataType,
void* data,
SORef *sor);
// the arrays are used to send one select/deselect event when a whole
lot
// of objects are selected/deselected. Sending 1000+ deselected
events is not a good
// idea
static CritRgn recentSelRgn;
static CFMutableSetRef recentlySelected;
static CFMutableSetRef recentlyDeselected;
static OSStatus PostMassSelOfOwner(SOOwnerID ID, Boolean selOrDesel,
CFArrayRef itsItems);
static OSStatus PostMassSelectEvents(SOOwnerID whichID=0); // clears
both arrays after sending
// dtEventKindObjectsSelected & dtEventKindObjectsSelected
// If zero is passed, all are sent (in seperate events for each ID)
OSStatus AddToSelected();
OSStatus AddToDeselected();
void SOCleanup();
public:
SelectedObject(SelObjectClass theObjClass, SOOwnerID ID);
SelectedObject(const SelectedObject &obj);
virtual ~SelectedObject();
UInt16 Retain();
UInt16 Release();
SelObjectClass GetObjectClass();
virtual SelObjectType GetObjectType(); // NYI. Will always return
zero.
SOOwnerID GetOwnerID();
virtual CFStringRef CopySOString();
virtual UInt64 GetSOData64(); // these two will always return zero
for the base class
virtual UInt32 GetSOData32(); // it is up to the subclasses to return
the correct values
SelectionFlag GetSelectFlags();
void DefineSelectFlag(SelectionFlag theFlags, Boolean newValue);
void ToggleSelectFlag(SelectionFlag theFlags);
Boolean IsSelectedOr(SelectionFlag whichFlags); // returns true if
any of the passed flags are set
Boolean IsSelectedAnd(SelectionFlag whichFlags); // returns true if
all of the passed flags are set
Boolean AnySelection(); // returns true is any flag is set
void PostSelectedEvent(Boolean selected);
virtual Boolean operator==(SelectedObject &obj);
virtual void DebugPrint(UInt32 v=0); // printf
virtual CFStringRef DebugString(UInt32 v=0); // CFStringRef -> CFShow
};
//-----------------------------------------------------------------------
--------------
class SelectedFileObject

ublic SelectedObject {
OSType sfoReady;
protected:
FSRef fsr;
virtual OSStatus CheckCache(SelObjectClass objClass, UInt16 dataType,
void* data,
SORef *sor);
void SFOCleanup();
public:
SelectedFileObject(const FSRef* fsrptr, SOOwnerID ID);
SelectedFileObject(const char* cpath, SOOwnerID ID);
SelectedFileObject(CFURLRef url, SOOwnerID ID);
SelectedFileObject(const SelectedFileObject &obj);
~SelectedFileObject();
CFStringRef CopySOString();
UInt64 GetSOData64();
UInt32 GetSOData32();
FSRef* GetFSRefPtr();
virtual CFStringRef CopyName();
Boolean operator==(SelectedFileObject &obj);
void DebugPrint(UInt32 v=0); // printf
CFStringRef DebugString(UInt32 v=0); // CFStringRef -> CFShow
};
typedef class SelectedFileObject* SelectedFORef;
typedef SelectedFORef SOFORef;
The plugin header uses this typedef:
// parent class
typedef void* SelectedObjectRef;
typedef SelectedObjectRef SORef; // shorter name
// selected file objects
typedef void* SelectedFileObjectRef; // subclass of SORef
typedef SelectedFileObjectRef SOFORef;
Here is the casting routine: (it is exported using extern "C")
SOFORef SOCastToSOF(SORef sor) {
if (sor==nil) {return nil;}
SelectedFORef sof=nil;
printf("%s\n", typeid(*sor).name()); (1)
printf("%s\n", typeid(SelectedFileObject).name()); (2)
if (typeid(*sor)==typeid(SelectedFileObject)) { (3)
sof=(SOFORef)sor;
}
else {sof=nil;}
// sof=dynamic_cast<SelectedFORef>(sor);
return sof;
};
The routine is used by plugins.
The plugins receive a SORef from the parent application via another
accessor routine and are
passed in an CFArray.
All the plugins ever receive are pointers.
The passed SORef is not guaranteed to be a SOFORef (much like a CFType
is not guaranteed to be a CFString). So they use this routine to convert
it if possible.
(1) & (2) typeid statements print '18SelectedFileObject' .
(3) always evaluates to false when the routine is called by the plugin.
But, if the owning app calls this casting routine directly, it succeeds.
Someone from a C++ newsgroup suggested that the vtable is getting 'lost'
or mangled when passed through the plugin.
Last bit of code. The CFArray callbacks:
const void* SORefRetain(CFAllocatorRef alloc, const void* value) {
SORef sor=(SORef)value;
sor->Retain();
return value;
};
void SORefRelease(CFAllocatorRef alloc, const void* value) {
SORef sor=(SORef)value;
sor->Release();
};