Hi Larry,
I created NEW_ABS_OPERATION &LONG in Global Data
Then added this line it here:
NEW_ABS_OPERATION &= New(ABS_OPERATION)
ABS_OPERATION.OperationID=0
ABS_OPERATION.Context=Address(ABS_Context_Data) !Null
ABS_OPERATION.Callback=Address(ABS_CALLBACK)
ABS_OPERATION.TimeOut=18000
ABS_OPERATION.Flags=ABS_OPERATION_FLAG_LL_CALLBACK
I get these errors:
Invalid variable data parameter type: ABS_OPERATION
Illegal data type: ABS_OPERATION
Starting to read up on New and Disposal, I didn’t realize the order of these things. Thanks for help.
V/R,
~Peter
Peter,
That would be very wrong. The API ABSEnroll() expects the address of the group (structure). The reference variable is very different.
The function is declared like this:
/**
* Scan the live finger, process it into a fingerprint template and return it
* to the caller.
*
* @param hConnection Handle to the connection to FM.
* @param pOperation See description of ABS_OPERATION.
* @param ppEnrolledTemplate Address of the pointer, which will be set to
* point to the resulting template (BIR). The template has to be discarded
* by a call to ABSFree.
* @param dwFlags Reserved for future use. Set to zero.
* @return Status code.
*/
ABS_STATUS BSAPI ABSEnroll(
IN ABS_CONNECTION hConnection,
IN ABS_OPERATION* pOperation,
OUT ABS_BIR** ppEnrolledTemplate,
IN ABS_DWORD dwFlags
);
You’ll note that ppEnrolledTemplate is a pointer to a pointer to the memory and pOperation is a pointer to the memory (one less level of indirection). A Clarion reference variable is only similar to a C pointer to a simple data type.
Note:
I prefer to prototype functions that expect pointers to a structure with a named group in Clarion. They’re always passed by address. Then you don’t have to use address(ofsomething) in the prototype and the compiler will tell you when you mess up. Also it’s good form to always use labels in your prototype.
Finally to pass a pointer to a pointer to an external function with the RAW attribute you can prototype it as *Long and then use the label of a long that contains the address of the memory, Just like tset[slot] does.
Also the debugger is your friend here. Make a trivial example and learn how to use the L and E functions. It’ll show you the exact memory pointed to by the address,
Larry again thanks,
I realized my mistake of the reference when looking at the documentation more closely and getting compile errors. I still don’t have the NEW() working correctly.
Naming conventions are very helpful and good programming to be consistent and relative naming is imperative when someone else is reading the code. I agree.
I will take another more learned shot at this again tomorrow. I am glad I feel I am making progress and thanks for your help.
Larry,
Yes debugger, I watched some on Clarion Live. Haven’t used it since Clarion Dos 2.0 days, I haven’t been keeping up with debugger since it has been driving me crazing. It seems the ClarionLive webinar will be helpful and getting that template utility.
I know my message() statements don’t cut it on debugging prototypes.
The Clarion debugger is the most useless one that I’ve ever used. However, it is very useful in these situations. Make the smallest hand coded test example project that you can and you’ll find that you can trace the pointers to memory locations (L and then E). As I noted before you might run into problems with the way the structures are allocated in C vs Clarion. (Dword vs Byte packing). You’ll be able to see that in the debugger. Or if you have a simple example in C, do sizeof(structure) and compare that to size(group) in Clarion. Of course that doesn’t work for the variable sized structs …
As I noted before you might run into problems with the way the structures are allocated in C vs Clarion. (Dword vs Byte packing).
Am I wasting my time?
BTW, the ClarionWiki was using DbView from SysInternals.
~Peter
Larry,
Compiling errors, changed GROUP to CLASS resolved, will this work though?
These were the errors with GROUP:
Invalid variable data parameter type - C:\dcsapp\Clarion10\UPEK\Upek002.clw:131,38
Illegal data type: ABS_OPERATION_REF - C:\dcsapp\Clarion10\UPEK\Upek002.clw:131,38
ABS_OPERATION_REF &= New(***ABS_Operation_GROUP***)
ABS_OPERATION_REF.OperationID=0
ABS_OPERATION_REF.Context=Address(ABS_Context_Data) !Null
ABS_OPERATION_REF.Callback=Address(ABS_CALLBACK)
ABS_OPERATION_REF.TimeOut=18000
ABS_OPERATION_REF.Flags=ABS_OPERATION_FLAG_LL_CALLBACK
ABS_Operation_Group GROUP, TYPE
OperationID ULONG
Context Long
Callback Like(ABS_CallbackID)
TimeOut LONG
Flags ULONG
End
ABS_OPERATION_REF &ABS_Operation_Group
Changed definition to:
ABS_Operation_Group CLASS, TYPE
OperationID ULONG
Context Long
Callback Like(ABS_CallbackID)
TimeOut LONG
Flags ULONG
End
ABS_OPERATION_REF &ABS_Operation_Group
Unable to test as I am not local to the machine and device, will class work?
Just use a Long for the callback procedure pointer like this:
ABS_Operation_Group GROUP, TYPE
OperationID ULONG
Context Long
Callback Long
TimeOut LONG
Flags ULONG
End
Unless I’m missing something, I don’t see a reason for the reference variable. You have to allocate the memory to call the function anyway. So just use Like()
ABS_Operation Like( ABS_Operation_Group)
Then use Address(ABS_Operation) in the call if ABSEnroll() is prototyped with a Long for that parameter.
ABS_Operation.OperationID=0
ABS_Operation.Context=Address(ABS_Context_Data) !Null <-- if that's supposed to be Null, set it to Zero
ABS_Operation.Callback=Address(ABS_CALLBACK)
ABS_Operation.TimeOut=18000
ABS_Operation.Flags=ABS_OPERATION_FLAG_LL_CALLBACK
Hi Larry,
No compile error but not getting a template either. I tried changing naming as suggested for readability.
Also came across this and I am wondering why I wouldn’t use CLASS instead of GROUP.
From CLASS(object declaration in help under Instantiation)
A FILE, GROUP, QUEUE, or CLASS declaration with the TYPE attribute is not allocated any memory. While the data members of a CLASS with the TYPE attribute are not allocated memory, the methods prototyped in the CLASS must be defined for use by any subsequent objects declared as that type. EXTERNAL and DLL are irrelevant. The PRIVATE attribute is also allowed for TYPE declarations.
If there is no TYPE attribute on the CLASS, the CLASS structure itself declares both the CLASS and an object instance of that CLASS. A CLASS with the TYPE attribute does not create an object instance of the CLASS.
For example, the following CLASS declaration declares the CLASS as a data type and an object of that type:
MyClass CLASS !Both a data type declaration and an object instance
MyField LONG
MyProc PROCEDURE
END
So if I drop the word TYPE the NEW() and Dispose() is not required it is automatic.
Shouldn’t I use CLASS instead of GROUP and drop the declaration of TYPE then the NEW() would not be needed, yes?