How can a C typedef stucture containing an array be converted to a clarion structure?

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.

Larry

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

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.

V/R,
~Peter

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.

V/R,
~Peter

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 …

Larry

Larry,

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?

~Peter

Peter,
Which was line 131?

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

Larry

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?

What say you?
~Peter