Sharing `Static` Methods Between Classes in a Single File in Objective-C
I am baffled by a static
method whose definition apparently lives in one class, but whose declaration is shared between several classes in the same file. Can it be shared between files somehow?
The Details
I'm trying to divide a .mm
file into several files (one per class). All of the source code is from Pete Goodliffe's CoreMIDI Example.
I took the PGMidi class from here and busted it up into separate interfaces and classes. Everything compiles perfectly except for one method marked static
, which needs to be in two places at once (it's "used but never defined" in PGMidi). The method is "used" in this line outside of any class implementation:
static void PGMIDIReadProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon);
which is apparently shared by all classes in the same file (what?). It's mentioned in two classes.
1) In PGMidi
, where it's used (perhaps pointing to PGMidiSource
s = MIDIInputPortCreate(client, (CFStringRef)@"MidiMonitor Input Port", PGMIDIReadProc, self, &开发者_如何学编程inputPort);
2) In PGMidiSource
, where the method body is defined
static
void PGMIDIReadProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon)
{
PGMidiSource *self = (PGMidiSource*)srcConnRefCon;
[self midiRead:pktlist];
}
The problem is that the self
referred to in the method body makes no sense in PGMidi
(no midiRead
method)...
What is this static
method? How I can get it to work between two files?
The static function is just a normal C function. The 'static' means it can only be accessed from within the same file. So you need to either:
Redefined it for every file you want use it from, typically by putting the entire static function definition in a header and include the header in every file you want to use it, or
Make it a non-static function and put the function prototype in a header, then include the header in every file you want to use it from.
On a function, the static
keyword roughly means "only visible and usable from within this file". Since it was defined in PGMidiSource.mm
, you cannot call it from PGMidi.mm
. Luckily, this is fairly easy to fix.
Declare the function prototype in
PGMidiSource.h
, like this:void PGMIDIReadProc(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon);
Remove the
static
keyword inPGMidiSource.mm
, since it needs to be usable from outside that file.
Note that this is not a "method"; it is a C function. As such, it belongs to no class, is not tied to any instance, has no access to any instance variables, etc. Any context that it needs must be passed in as a parameter. Hence, while this function uses a variable called "self", it's actually just a local alias for one of the parameters that was passed in.
The reason that it looks like that "method" is shared between multiple classes is because it's not technically a method. Instead, that's a C function. You can add C to Objective C in that manner, and that particular function can be invoked from multiple files, though it's a good practice to provide a "prototype" in a header file for the files that don't have the actual function implemented within them. (Or it was the last time I wrote in C. It's been a while.)
If you don't provide the prototype in the other files, C will let you go merrily on your way (though the compiler will probably say it doesn't know anything about that function in a warning.) But the linker will resolve it, and assuming it's coded correctly, it should work.
精彩评论