How to write a wrapper?

Started by Midimaster, April 01, 2021, 14:59:29

Previous topic - Next topic

col

Or even this if you wanted to chain them

Code (BlitzMax) Select

Print MiniAudio.FormatEnums.ma_format_f32

Type ma_format_enum
    Const ma_format_unknown:Int = 0
    Const ma_format_u8:Int      = 1
    Const ma_format_s16:Int     = 2
    Const ma_format_s24:Int     = 3
    Const ma_format_s32:Int     = 4
    Const ma_format_f32:Int     = 5
EndType

Type MiniAudio
    Global FormatEnums:ma_format_enum = New ma_format_enum
EndType
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

Midimaster

You misunderstood me. My second example was about the question if it is possible to directly refer to the c-code without any B
BlitzMax constants or types.

of course I know how to design constants in any way in BlitzMax. All my questions here in this thread are always C-related.



...back from North Pole.

Henri

You can use miniaudio constants (or enums) in C if you include the relevant header file.

But you can't use those in Blitzmax without declaring them first in Blitzmax.

-Henri

Ps. If I too misunderstood what you meant then please elaborate more..
- Got 01100011 problems, but the bit ain't 00000001

Midimaster

upps...

is it not very polite to write:
"...You misunderstood me..."
???

if this sound "harsh" and impolite, I need to say, that this is only because of my bad english. I don't want to sound "harsh". I'm very happy to get all these help.

...back from North Pole.

Derron

Henri just wrote that if he did misunderstood you, that you might write "more" (more in depth) so he has better chances to understand you.

---
in German for you (to calm down your heart :))
Henri hat nur mitgeteilt, dass er - falls er Dich missverstanden hat - Dich bittet, mehr ins Detail zu gehen.



bye
Ron

col

Quoteis it not very polite to write:
"...You misunderstood me..."

Nah no worries. I understand English isn't everyones first language. I didn't think it was negative at all.
Everything's all good, and the more people that chime in to help the better - especially when it comes to a misunderstanding from language. 8)

I think Henri answered your question more accurately?
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

Derron

#51
Quote from: col on April 08, 2021, 16:43:24
Everything's all good, and the more people that chime in to help the better - especially when it comes to a misunderstanding from language. 8)

I cannot write much in "C". But am quite good writing in "DE" :)


bye
Ron

col

Quotethat this is only because of my bad english
Your English is far far better than any other spoken language I would attempt :D

QuoteBut am quite good writing in "DE"
Just 'E' for me. Heh I just remembered the 'E' programming language for the Amiga. Nowadays it looks like a hybrid of C, Python and BMax in syntax.
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

Midimaster

#53
* EDIT  *  looks like working now! I updated code and zip.


Ok, next step...



now one of the fields in the STRUCT is a callback adress, where you store the adress of a function which is in your code and which is called from the Miniaudio-Driver in intervals.

typedef void (* ma_device_callback_proc)(int pDevice, void* pOutput, const void* pInput, int frameCount);

struct ma_device_config
{
    ma_device_type deviceType;
    int sampleRate;
    ...
    ma_device_callback_proc dataCallback;
    //.....
};


// my simulation save Callback :

extern void SetCallBack(struct ma_device_config *config, ma_device_callback_proc *Callback) {
printf("FILL_CALLBACK \n");
config->dataCallback= Callback;
printf("set callback pointer= %i \n", config->dataCallback);
}


at the moment I simulate the callback with a INTEGER:
Code (BlitzMax) Select

SuperStrict
Import "lern.c"
Global MiniAudio:Byte Ptr=GetDevice(1)

Local Pointer: Byte Ptr = Callback
Global TestValue%

Print "pointer=" + pointer

SetDevice MiniAudio, 16, 2, 44100
SetCallback Miniaudio, pointer

Function CallBack(a%, b:Byte Ptr, c:Byte Ptr, d%)
TestValue=d
End Function

Extern
Function GetDevice:Byte Ptr( DeviceTyp:Int ) ="StartDeviceGlue"
Function SetCallBack ( DeviceRAM:Byte Ptr, CallBack: Byte Ptr)
End Extern



But my question is: Is this already correct? What does this variable dataCallback from typ ma_device_callback_proc expect? Is this ,how can I send a function to it?


The complete code is attached as a ZIP included a table, at which line number you can find the original functions in Miniaudio.h
(lern.c & lern.bmx & WhereIsIt.txt)
...back from North Pole.

Midimaster

#54
The next function call brings a lot of problems and me again to my limits:

the given function is:
MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice);



for testing purpose and pointing to the problem it is enough to (at first) simulate the function with one parameter:

struct ma_device
{
    //ma_context* pContext;
    //ma_device_type type;
    int sampleRate;
    //......
};

void ma_device_init ( ma_device* pDevice);


Why is it possible in the original code to define the function like this without STRUCT as prefix. And I'm not able to do that and receive an error message:
C:/BasicNG/FreeAudio/lern.c:56:21: error: unknown type name 'ma_device'
void ma_device_init(ma_device* pDevice)
                     ^~~~~~~~~
                     ma_device_type


when I would write it this way it works.
void ma_device_init ( STRUCT ma_device* pDevice);

But this is a given function of MiniAudio.h. I must call it as it is.

Is there anything I forgot?
...back from North Pole.

col

You can use...

typedef struct ma_device ma_device;

so that you don't need to keep putting struct in front of the type every time you want to use it.

https://en.m.wikipedia.org/wiki/Typedef
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

Midimaster

Thank you. This was new to me. It works!

And now I find a lot of those lines also in the MiniAudio.h too. Of course.

The file MiniAudio.h is not very good for learning because it has >65000 lines and I have no chance to find such lines, because the are not  in the context of the STRUCT or closed to a function which use it. But they are there.
...back from North Pole.

Midimaster

Today I found out how to define a c-function, which calls back a BlitzMax-function:

Code (BlitzMax) Select

SuperStrict
Import "lern.c"
Global TestValue:Int=0
Local MyPointer: Byte Ptr = MyCallback
TenCallbacks( MyPointer)

Function MyCallBack(a:Int)
TestValue = TestValue + a
Print "BlitzMax-Call=" + TestValue
End Function

Extern
Function TenCallbacks (CallbackPointer: Byte Ptr)
End Extern



now the "lern.c":

typedef void (* callback_proc)(int a);

void TenCallbacks(callback_proc *pointer){
printf("SIMULATE TEN CALLBACK \n");
printf("see callback pointer= %i \n", pointer);
callback_proc InternPointer = pointer;
for (int i=0; i<=10; i++){
(* InternPointer) (7);
}
}


You create a function in BlitzMax and store the pointer to it in a Byte Ptr
The you define the same function in C without content:
typedef void (* callback_proc)(int a);

If you know the pointer in C you now can call the BlitzMax-function.
callback_proc InternPointer = pointer;
(* InternPointer) (7);




But one Question remains...

I wanted to show how easy is it to implement a Callback in C, but again I need something which I do not understand. Why do I need a local InterPointer variable and cannot work directly with the pointer:

this works:
void TenCallbacks(callback_proc *pointer){
printf("get callback pointer= %i \n", pointer);
callback_proc InternPointer = pointer;
(* InternPointer) (7);
}



and this not:
void TenCallbacks(callback_proc *pointer){
printf("get callback pointer= %i \n", pointer);
(* pointer) (7);
}
...back from North Pole.

col

#58
You got it working, kind of. Well done  8)

In your existing code you have the parameter as a pointer to the callback. This is unnecessary because callback_proc is already the address of the function (a function pointer). So if you remove the pointer in the parameter you will be able to call it as you expect :


typedef void (* callback_proc)(int a);

// Remove the '*' from the parameter:
void TenCallbacks(callback_proc pointer){
printf("SIMULATE TEN CALLBACK \n");
printf("see callback pointer= %i \n", pointer);
for (int i=0; i<=10; i++){
pointer(7);
}
}


You can do something like the following to double check your function pointer address in BMax:

Local MyPointer: Byte Ptr = MyCallback
Print("BMax Function Pointer: " + Int MyPointer)

Coupled with what you have in the c code to print out the callback function address - they should match.


You have to be super careful when doing this kind of stuff as there is absolutely zero marshalling between the 2 languages so it's easy to get it wrong - especially the pointer stuff - Keep going though as you're getting there  8)
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."

col

If I recall correctly you can skip the Byte Ptr variable in the BMax code. So you should be able to use something like this directly too:

Code (BlitzMax) Select

SuperStrict
Import "BMaxTest.c"
Global TestValue:Int=0
Print("BMax Function Pointer: " + Int Byte Ptr MyCallback)
TenCallbacks( MyCallBack)

Function MyCallBack(a:Int)
        TestValue = TestValue + a
        Print "BlitzMax-Call=" + TestValue
End Function

Extern
        Function TenCallbacks (CallbackPointer: Byte Ptr)
End Extern
https://github.com/davecamp

"When you observe the world through social media, you lose your faith in it."