View Single Post
Old 28 December 2013, 13:49   #13
FrodeSolheim
FS-UAE Developer

FrodeSolheim's Avatar
 
Join Date: Dec 2011
Location: Førde, Norway
Age: 36
Posts: 3,368
Well, I completely agree that the native function itself will receive a data structure, which can contain the UAE native interface version number, arguments from m68k and helper function pointers. Extensibility would be ensured by only adding new stuff to the end of the struct of course, and version information in the struct can allow the native function to know what struct members are valid. Another good idea is to let the native library specify a minimum supported "UAE Native Interface" version, so the native functions are not used at all if the library requires too new features.

But you also said "m68k-side parameter structure" and that's where I don't immediately see an advantage. Since there isn't a compiler involved to match the function calls, there isn't any way to enforce a standard anyway (I mean check that it is used correctly).

Sure we could mandate that the m68k sets up a struct, but that would either have to be something like this predefined struct (ignoring data types):
Code:
struct {
    result;
    param1;
    param2;
    param3;
    param4;
}
or something like this:
Code:
struct {
    result;
    ....
}
(and the native function must know what fields following result are valid).

I don't think either of these cases are significantly better than just passing values in the registers. In all cases, there is an implicit contract between the Amiga-side caller and the native callee - knowing what data is passed where - and breaking that contract will have bad consequences. I guess one use for a standard argument passing structure is if the native interface layer would always like to be able to pass some kind of exception/error information back to the caller, but I'm not sure how useful that would be.

As for the native functions themselves, they could look something like this:

Code:
void (*native_function)(struct uni_data* uni);
Where the uni_data struct could look like something like this:

Code:
struct uni_data {
    uae_u32 version;  // native interface version
    uae_u32 a1, a2, a3, a4, a5, a7;
    uae_u32 d1, d2, d3, d4, d5, d6, d7;
    void * (*get_real_address)(uae_u32 ptr);
    /* more helper functions and extensibility for future fields */
};
Library should define a function like this (just reusing the previous struct here in this example though the register fields are obviously not useful here):

Code:
uae_u32 uni_init(struct uni_data* uni) {
    if (uni->version < UNI_MIN_VERSION) {
        return 0;
    }
    return 1;
}
Of course, versioning the native libraries themselves is also useful, but that could be left to the library authors (call a native function from the library to check library version and/or capabilities).

Last edited by FrodeSolheim; 29 December 2013 at 00:36.
FrodeSolheim is offline  
 
Page generated in 0.05136 seconds with 9 queries