B4R Question Using variables outside of "inline c"

highco

Member
Licensed User
Longtime User
Hi,
Is it possible to utilise the variables that are used in "inline c" outside , in B4R ?
Can I pass a variable into "inline c" as well ?
An example would be of great help,
Regards
Terry
 

emexes

Expert
Licensed User
I don't have B4R installed but assuming that it operates similarly to B4J:

I would look under the project's Objects directory for the compiled output C file.

With luck, there should be clues in that about how to access B4R variables from C.

It might be that you can only access global variables.
 
Upvote 0

candide

Active Member
Licensed User
in B4R variables can be byte, int, uint, Long, Ulong double, String and ArrayByte. ( but also ArrayInt, ArrayUint, ArrayLong, ArrayUlong, ArrayDouble)

between B4R and inline C we can use only one variable "Object" and an Object can support Long, Ulong, Double and a pointer. Long, Ulong, double and Pointer are inside Object.
Pointer is used to Const char* from B4RString or char* from Arraybyte
Pointer can be a pointer to an array of Objects if you go to inline C with an array of Object

conversion to Object is done automatically .
in inline C, you have to recover your variable :
first you can check o-> type to know what are parameters in this Object and after you can recover variables sent.
an example below where in your inline C you can recover Long, Ulong, Double, String or arraybyte :
B4X:
#if c
void myobject(B4R::Object* o) {
    byte Type = o->type;
    Serial.print("Object1 type : ");Serial.println(Type);  
    Long Long1; ULong ULong1; Double Double1; const char* cchar1; char* char1; B4R::Array* ar1;B4R::Array* ar2; B4R::Object** arrayOfPointers;
  
//case RunNative("myobject",-25)      
    if (Type == 5) { //Long
        Long1 = o->toULong();  
        Serial.print("content : ");Serial.println(Long1); }
//case RunNative("myobject",25)      
    if (Type == 6) { //ULong
        ULong1 = o->toULong();  
        Serial.print("content : ");Serial.println(ULong1); }
//case RunNative("myobject",25.32)      
    if (Type == 7) { //Double
        Double1 = o->toDouble();  
        Serial.print("content : ");Serial.println(Double1); }  
//case RunNative("myobject","inline C tests")      
    if (Type == 101) { //case string in const char*
        cchar1 = (const char *)B4R::Object::toPointer(o);  
        Serial.print("content : ");Serial.println(cchar1); }

//case RunNative("myobject","inline C tests".getbytes)
    if (Type == 100) { //case array direct
          ar1 = (B4R::Array*)B4R::Object::toPointer(o);
          char1 = (char*)ar1->data;
          Serial.print("content : ");Serial.println(char1); }
};
#End If

it is my understanding of Object used from B4R to inline C.
i hope i don't make mistake...

if you have several variables array, String, byte, etc... to send to inline C, you can create an array of Objects in B4R and send it to inline C
//example with :
Dim xx as Double == 25.678
Dim tsts() As Object = Array(xx,"azerty",1000,"next".getbytes,105.00,"last","10")
B4X:
#if c
void myobject(B4R::Object* o) {
    byte Type = o->type;
    Serial.print("Object1 type : ");Serial.println(Type);  
    Long Long1; ULong ULong1; Double Double1; const char* cchar1; char* char1; B4R::Array* ar1;B4R::Array* ar2; B4R::Object** arrayOfPointers;

// first you have to recover Array of Objects
    if (Type == 100) { //case array of Objects      
        ar1 = (B4R::Array*)B4R::Object::toPointer(o);      
        Serial.print("Array length : ");Serial.println(ar1->length);                 
        arrayOfPointers = (B4R::Object**) ar1->data;       
        B4R::Object* c[ar1->length];int i;
        for(i = 0; i <ar1->length; i++)
        {
          c= arrayOfPointers;    
          Serial.print("Object c[");Serial.print(i);Serial.print("] type : ");Serial.println(c->type);
          switch (c->type) { //test Object type
            case 5 : // Long
               Serial.print("value Long: "); Serial.println(c->toLong()); 
               break;            
            case 6 : // ULong
               Serial.print("value ULong: "); Serial.println(c->toULong());
               break;                
            case 7 : // Double
               Serial.print("value Double: "); Serial.println(c->toDouble());     
               break;        
            case 100 : //Pointer to char*
               ar2 = (B4R::Array*)B4R::Object::toPointer(c);
               char1 = (char*)ar2->data;
               Serial.print("content : ");Serial.println(char1); 
               break;        
            case 101 : //pointer to const char*        
               char2 = (const char  *)B4R::Object::toPointer(c);    
               Serial.print("content : ");Serial.println(char2);       }    }            
};
#End If
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Also you can reference b4r variables directly from in-line c code
B4X:
Sub Process_Globals
    Public Serial1 As Serial
    Dim myVar As Int
End Sub

Private Sub AppStart
    Serial1.Initialize(9600)
    Log("AppStart")
    RunNative("myTest",Null)
    Log(myVar)
End Sub
#if c
void myTest(B4R::Object* o){
    b4r_main::_myvar = 6;  // this is defined in b4r code
}
#End If
 
Upvote 0

Gerardo Tenreiro

Active Member
Licensed User
Hello, how could I access a PIN from C?
for example I have a pin defined in B4R

#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 1200
#End Region

Sub Process_Globals
Public Serial1 As Serial
Private Pin_Led As Pin
Private T_Led As Timer


End Sub

Private Sub AppStart
Serial1.Initialize(115200)
Log("Arranque de APP")
Pin_Led.Initialize(2,Pin_Led.MODE_OUTPUT)

T_Led.Initialize("T_Led_Tick",500)
T_Led.Enabled = True

RunNative("myTest",Null)
End Sub

Sub T_Led_Tick

End Sub

#if c
void myTest(B4R::Object* o){

digitalwrite(b4r_main::_pin_led,false)
}
#End If
and I want to activate or deactivate it from C
This code do not work

Thank you so much
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
The code works for simple variables int long etc

For more complex variables like String for example, you have to mimic what the variable needs.
B4X:
' b4r code
    Dim strVar As String

'c code
    b4r_main::_strvar->data = "Hello";
    b4r_main::_strvar->stringLiteral = true;

The above code will put Hello into strVar
 
Last edited:
Upvote 0

Gerardo Tenreiro

Active Member
Licensed User
El código funciona para variables simples, largas, etc.

Para variables más complejas como String, por ejemplo, debes imitar lo que la variable necesita.
[código]
'código b4r
Dim strVar como cadena

código c
b4r_main::_strvar->data = "Hola";
b4r_main::_strvar->stringLiteral = verdadero;
[/código]

El código anterior pondrá Hola en strVar
I don't see it clear about imitating the variable.
How can I imitate a Pin

My problem is that I need to deactivate a pin of the ESP32 some time after I activate it, it is for a very critical RS485 communication.
Thus in B4R I activate the EN_TX and queue the sending of the telegram, 2100us later I have to download it to be able to read the equipment's response. The telegram takes 2000us to come out through the RS485, the device responds in 500us, so I have 2100 to 2600us to lower the pin and go to reading.
Right now it is working because I am continually checking this time, this means that the ESP32 dedicates many of its resources to this task.
So the idea is to use the other core with a function in C that compares the moment where I activate the pin, which I leave it in a variable and the time later set the pin to False

I know it's very critical, but I can't think of any other solution.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
After a quick search in your case you probably need something like (not tested)
B4X:
digitalwrite(b4r_main::_pin_led->PinNumber , false);
 
Upvote 0
Top