Thread: Re: [Linux1394-devel] Announce: SDPAVC
Brought to you by:
aeb,
bencollins
From: Manfred W. <e95...@st...> - 2000-04-04 20:52:25
|
"Timothy M. Shead" wrote: > > After much playing around, I figured it out ... thanks! So, without > further ado, anyone interested in a C++ library for controlling devices > through AV/C (the protocol-of-choice for DV camcorders) should check-out > SDPAVC, located at my website: http://www.k-3d.com. The library, which Are you sure that this works. I neither compiled nor tested it, but I had a look at the code, and I see the following problem: Let's inspect the function sdpAvcSubUnit::RawCommand in sdpavcsubunit.cpp, especially line 105: raw1394_set_fcp_handler(m_Handle, FCPHandler); You try to register a handler, which has (ragarding to raw1394.h) to be of the type int (*)(raw1394handle_t, nodeid_t nodeid, int response size_t length, unsigned char *data). But according to line 134, your handler has the type int (sdpAvcSubUnit::*) (raw1394handle_t Handle, ... , unsigned char* Data). It is no ordinary function, but a member function of a class and incompatible to the type, raw1394_set_fcp_handler expects (because C++ adds a pointer to the object [the instance of the class] it belongs to as a "hidden" argument to the argument list of the function, which therefore has one parameter too many. I have the same problem. It is not possible to register a member function of a class as handler; it must be an ordinary C-function (which of course cannot access the member variable of the object [because it does not get that hidden pointer to that object]). One can work-around this by using global variables for everything the handler must access as long as there is only one object, but if there are two (or more) instances, there will be troubles (especially, if the application is multithreaded), because the handler wants to hand over things to one particular object, but the global variables are common to all objects. The objects can get individual raw-handles, but the fcp_handler (and the same applies to the iso_handlers) cannot find out, which object did the raw1394_loop_iterate (btw: you should replace raw1394_read in line 113 with a raw1394_loop_iterate-loop until the response-frame arrived) and thus cause it to be called. I do not know a "clean" solution to that problem (as long as we want to use libraw1394). I think, the only way would be to create a new object-oriented version of libraw. One quick solution might be to add a field "private" or something like that to struct raw1394_handle, which we could use to store a pointer to our object. Then we could declare the handler as a friend function of the class and via the pointer (because the handler has the raw-handle as first argument, and therefore would get that pointer) we could access the member variables of the object. Manfred Weihs |
From: Andreas B. <and...@mu...> - 2000-04-05 22:45:47
|
On Tue, Apr 04, 2000 at 10:44:51PM +0200, Manfred Weihs wrote: > I do not know a "clean" solution to that problem (as long as we want to > use libraw1394). I think, the only way would be to create a new > object-oriented version of libraw. > One quick solution might be to add a field "private" or something like > that to struct raw1394_handle, which we could use to store a pointer to > our object. Then we could declare the handler as a friend function of > the class and via the pointer (because the handler has the raw-handle as > first argument, and therefore would get that pointer) we could access > the member variables of the object. Or, which is cleaner, just use this object pointer to call a class function (no friend declaration necessary). I added: void *raw1394_get_userdata(raw1394handle_t handle); void raw1394_set_userdata(raw1394handle_t handle, void *data); Should be in CVS by the time you read this. -- Andreas E. Bombe <and...@mu...> DSA key 0x04880A44 http://home.pages.de/~andreas.bombe/ http://linux1394.sourceforge.net/ |
From: Manfred W. <e95...@st...> - 2000-04-06 00:33:27
|
"Timothy M. Shead" wrote: > You didn't notice that sdpAvcSubUnit::FCPHandler is a static member > function, meaning that it does not have an implicit "this" pointer, and thus > *does* have the correct prototype for use with raw1394_set_fcp_handler(). Ok. You are right. > [...discussion about ways to an object-oriented apporach...] > [...] So, would this require changes to just > libraw1394, or to the kernel code itself? I think: yes. In my opinion, the easiest way would be to store that private data in the raw-handle. For that purpose we would only have to adopt raw1394_private.h: struct raw1394_handle { int fd; unsigned int generation; nodeid_t local_id; int num_of_nodes; bus_reset_handler_t bus_reset_handler; tag_handler_t tag_handler; fcp_handler_t fcp_handler; iso_handler_t iso_handler[64]; struct raw1394_request req; quadlet_t buffer[2048]; void *private_data; // new private data to store pointer to object }; I think, that's all (I did not try it yet). Then after getting the handle via raw1394_get_handle (), we have to store our pointer in the handle. The rest would be - in your example: class sdpAvcSubUnit { // other stuff ... // ... this is the global callback function accessible by "C" ... static int RawFCPHandler(raw1394handle_t handle, nodeid_t nodeid, int response, size_t length, unsigned char *data); // This is the actual per-object callback method ... called from RawFCPHandler() ... unnecessary arguments eliminated int FCPHandler(nodeid_t nodeid, int response, size_t length, unsigned char *data); // other stuff ... }; int RawFCPHandler(raw1394handle_t handle, nodeid_t nodeid, int response, size_t length, unsigned char *data) { return ((sdpAvcSubUnit*) handle->private_data)->FCPHandler(nodeid, response, length, data); } int FCPHandler(nodeid_t nodeid, int response, size_t,length, unsigned char *data) { // Do whatever, access member data, etc. } Of course, it would also be possible to change the handler to get that user data as 6th argument; but my version requires less change of libraw1394. Manfred Weihs |