Share My Creation Hadouken - B4A Native Library Generator [Prototype]

Yet another one of my personal science experiments: Hadouken - B4A Native Library Generator! :)

So far, this project is nothing more than a prototype, it's very unstable and you are limited to the following C types:
short, int, long ,float, double, char, byte and bool.
You cannot pass or return any other kind of variables.

This program allows you to write simple C/C++ code and have all the functions compiled into a native (.so) library, which in turn is included in a Java lib ready to be used in B4A. When using already existing code, if present, the main() function will be automatically ignored by Hadouken.

Last Update: November 8th 2015
Please delete the following files/folder for a fresh update:
B4X:
<file>   config.txt
<folder> workspace
<folder> project
Download link:
http://www.ninjadynamics.com/stuff/hadouken.jar
Please do not save it in Program Files.
Instead, save it to a folder in a different location, as a workspace sub-directory needs to be created.

Reminder:
Please test your C/C++ code before trying to build a B4A library, as any kind of syntax error will crash the application.​

Instructions:

1. Please make sure you have installed the following required software:
2. Run Hadouken and provide the necessary software paths, as seen below.
Capture.png



3. Compile the example by clicking the big blue button.
snip.png

As seen above, B4A library files were be generated and saved in the additional libs folder.


4. Add the library to your B4A project and write some code for it.
snip2.png



5. As you can see, it works! (sometimes)
snip3.png
 

Attachments

  • hadouken.png
    hadouken.png
    176.5 KB · Views: 2,729
Last edited:

jahswant

Well-Known Member
Licensed User
Longtime User
I will watch execution time and memory issues as more as you advance...Courage...
 

Informatix

Expert
Licensed User
Longtime User
Your program should offer to choose the ABI because generating everything by default is excessive.

What "Hadouken" means? It sounds like a jewish holiday.

If one wants to log something, here's how to do:
In the C code:
#include<android/log.h>
__android_log_write(ANDROID_LOG_VERBOSE, "B4A", "Your message");
__android_log_write(ANDROID_LOG_VERBOSE, "B4A", "Your numbers %d %f", MyInt, MyFloat);
In Android.mk:
LOCAL_LDLIBS := -llog
 

wonder

Expert
Licensed User
Longtime User
Your program should offer to choose the ABI because generating everything by default is excessive.
I will take that into consideration. :)
What "Hadouken" means? It sounds like a jewish holiday.
It's a fighting move from the Street Fighter game series:
Hadouken
Hadouken or Hadoken (波動拳 Hadōken?, IPA: [hadoːkẽꜜɴ], literally "wave motion fist" or "surge fist"), is a special attack used by Ryu, Ken, and other Street Fightercharacters. Takashi Nishiyama, the creator of Street Fighter, credits the 1970s anime Space Battleship Yamato and a missile called the Hadouho as the origin of Hadouken.[59] The move is achieved by the characters thrusting their palms forward, sending a surge of spirit energy, or ki, flying towards the opponent. It is normally performed by the player moving the joystick or D-pad a quarter circle forward towards the opponent from the down position, then pressing a punch button. Although the execution has been always the same, the design, speed, damage, and other attributes of the technique vary in different games.[60]

@jahswani, does it work for you? :)
 

JordiCP

Expert
Licensed User
Longtime User
Great job! This can save a lot of work for people who don't feel comfortable with Java but know C/C++

This is specially useful if you are developing the C part, to shorten the loop: edit, compile, build all, test ....


A good point would be if one could edit the C file in the B4A IDE. Now it does not allow to add external documents to the project...
 

wonder

Expert
Licensed User
Longtime User
Thank you! :)
I will try to add support for Strings, Arrays and Java Objects in the following weeks.

Performance wise, I did some tests calculating (iterative) the Nth number in the Fibonacci sequence.
The native code performed way faster. Hopefully we'll be able to create some cool stuff in the future.
 
Last edited:

JordiCP

Expert
Licensed User
Longtime User
Adding support for other objects would be nice. But it is more complicated than working with primitive objects, which are passed by value

Arrays and jobjects in general are passed as a reference. The user needs to syncronize with the system to use them

For instance, with arrays:

B4X:
void sum_three(int* wSrc, unsigned int wHowManyArrayElements){

    unsigned int k;
    volatile uint32_t * A ; //pointer of the same type as the array elements
    A = (uint32_t*)(*env)->GetPrimitiveArrayCritical(env,wSrc,NULL); //Ask permission to the system and returns a pointer

    // now you can work with "A", which points to the contents of wSrc normally, as the pointer to the array elements
    k=wHowManyArrayElements;
    while(k--){
        (*A)+=3;
        A++;
    }

    // return control of "wSrc" to Android
    (*env)->ReleasePrimitiveArrayCritical(env,wSrc,(void*)A,JNI_COMMIT); //or JNI_ABORT if you don't want to save changes
}

For bitmaps there are also assotiated functions.

Performance wise, I did some tests calculating (iterative) the Nth number in the Fibonacci sequence.
The native code pgerformed way faster. Hopefully we'll be able to create some cool stuff in the future.

Much faster...although optimizing code architecture is the very first thing to do in order to gain speed ;)
Also, changing compiler optimization directives in Android.mk gives very different results
...and if you use assembler for the most critical parts, then it will fly!!:D
 

walterf25

Expert
Licensed User
Longtime User
Yet another one of my personal science experiments: Hadouken - B4A Native Library Generator! :)

So far, this project is nothing more than a prototype, it's very unstable and you are limited to the following C types:
short, int, long ,float, double, char, byte and bool.
You cannot pass or return any other kind of variables.

This program allows you to write simple C/C++ code and have all the functions compiled into a native (.so) library, which in turn is included in a Java lib ready to be used in B4A. When using already existing code, if present, the main() function will be automatically ignored by Hadouken.

Download link:
http://www.ninjadynamics.com/stuff/hadouken.jar
Please do not save it in Program Files.
Instead, save it to a folder in a different location, as a workspace sub-directory needs to be created.

Reminder:
Please test your C/C++ code before trying to build a B4A library, as any kind of syntax error will crash the application.​

Instructions:

1. Please make sure you have installed the following required software:
2. Run Hadouken and provide the necessary software paths, as seen below.

snip1.png



3. Compile the example by clicking the big blue button.
snip2.png

As seen above, B4A library files were be generated and saved in the additional libs folder.


4. Add the TestLib to your B4A project and write some code for it.

snip3.png



5. As you can see, it works! (sometimes)

snip4.png
Very nice!
 

wonder

Expert
Licensed User
Longtime User
By the way, all the generated Java and C/C++ code can be found in the "project" and "workspace" folders respectively. :)
I hope I got everything right so far.
 
Last edited:

wonder

Expert
Licensed User
Longtime User
Very nice!
Great work
Good job!
Thank you, thank you and thank you!! :)

I've released a more robust new version, which includes a more complex C/C++ example.
It includes most of the math functions found in <math.h> and some functions of my own.

I call it NinjaCore. :D
B4X:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include <time.h>

static const long double   PI = 3.141592653589793238462643383279502884197169399375105;
static const double toRADIANS = 0.017453292519943295769236907684886127134428718885417;
static const double toDEGREES = 57.29577951308232087679815481410517033240547246656432;

bool CollisionBetweenCircles(double x1, double y1, double r1, double x2, double y2, double r2);
bool CollisionBetweenSpheres(double x1, double y1, double z1, double r1, double x2, double y2, double z2, double r2);
bool CollisionPointInRectLT(double pX, double pY, double rectLeft, double rectTop, double rectWidth, double rectHeight);
bool CollisionPointInRect(double pX, double pY, double rectCenterX, double rectCenterY, double rectWidth, double rectHeight);
bool CollisionRectInRect(double rect1Left, double rect1Top, double rect1Right, double rect1Bottom, double rect2Left, double rect2Top, double rect2Right, double rect2Bottom);
double cCos(double x);
double cCosD(double x);
double cSin(double x);
double cSinD(double x);
double cACos(double x);
double cACosD(double x);
double cASin(double x);
double cASinD(double x);
double cTan(double x);
double cTanD(double x);
double cATan(double x);
double cATanD(double x);
double cATan2(double y, double x);
double cATan2D(double y, double x);
double cMax(double x, double y);
double cMin(double x, double y);
double cDim(double x, double y);
double cAbs(double x);
double cRemainder(double x, double y);
double cRound(double x);
double cFloor(double x);
double cCeil(double x);
double cTrunc(double x);
double cSqrt(double x);
double cPow(double x, double y);
double cCbrt(double x);
double cHypot(double x, double y);
double DistanceBetween2D(double x1, double y1, double x2, double y2);
double DistanceBetween3D(double x1, double y1, double z1, double x2, double y2, double z2);
double PointOfCollisionBetweenCircles_X(double x1, double r1, double x2, double r2);
double PointOfCollisionBetweenSpheres_X(double x1, double r1, double x2, double r2);
double PointOfCollisionBetweenCircles_Y(double y1, double r1, double y2, double r2);
double PointOfCollisionBetweenSpheres_Y(double y1, double r1, double y2, double r2);
double PointOfCollisionBetweenSpheres_Z(double z1, double r1, double z2, double r2);
double PointOfIntersectionBetweenLines_X(double Ax, double Ay, double Bx, double By, double Cx, double Cy, double Dx, double Dy);
double PointOfIntersectionBetweenLines_Y(double Ax, double Ay, double Bx, double By, double Cx, double Cy, double Dx, double Dy);
double PostCollisionVelocity(double u1, double u2, double m1, double m2, double CoR);
double RandomNumber(int lowest, int highest, int decimalPlaces, bool preventZero);


double cCos(double x)
{
    return cos(x);
}

double cCosD(double x)
{
    double n = truncl(x / 360);
    if (x > 360) {
        x -= (360 * n);
    }
    else if (x < 360) {
        x += (360 * n);
    }
    if (x == 90 || x == 270 || x == -90 || x == -270) {
        return 0;
    }
    return cos(x * toRADIANS);
}

double cSin(double x)
{
    return sin(x);
}

double cSinD(double x)
{ 
    double n = truncl(x / 360);
    if (x > 360) {
        x -= (360 * n);
    }
    else if (x < 360) {
        x += (360 * n);
    }
    if (x == 0 || x == 180 || x == -180) {
        return 0;
    }
    return sin(x * toRADIANS);
}

double cACos(double x)
{
    return acos(x);
}

double cACosD(double x)
{
    return acos(x * toRADIANS) * toDEGREES;
}

double cASin(double x)
{
    return asin(x);
}

double cASinD(double x)
{
    return asin(x * toRADIANS) * toDEGREES;
}

double cTan(double x)
{
    return tan(x);
}

double cTanD(double x)
{
    return tan(x * toRADIANS);
}

double cATan(double x)
{
    return atan(x);
}

double cATanD(double x)
{
    return atan(x) * toDEGREES;
}

double cATan2(double y, double x)
{
    return atan2(y, x);
}

double cATan2D(double y, double x)
{
    return atan2(y, x) * toDEGREES;
}

double cMax(double x, double y)
{
    return fmax(x, y);
}

double cMin(double x, double y)
{
    return fmin(x, y);
}

double cDim(double x, double y)
{
    return fdim(x, y);
}

double cAbs(double x)
{
    return fabs(x);
}

double cRemainder(double x, double y)
{
    return remainder(x, y);
}

double cRound(double x)
{
    return round(x);
}

double cFloor(double x)
{
    return floor(x);
}

double cCeil(double x)
{
    return ceil(x);
}

double cTrunc(double x)
{
    return trunc(x);
}

double cSqrt(double x)
{
    return sqrt(x);
}

double cPow(double x, double y)
{
    return pow(x, y);
}

double cCbrt(double x)
{
    return cbrt(x);
}

double cHypot(double x, double y)
{
    return hypot(x, y);
}

double DistanceBetween2D(double x1, double y1, double x2, double y2)
{
    return sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
}

double DistanceBetween3D(double x1, double y1, double z1, double x2, double y2, double z2)
{
    return sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)) + ((z2 - z1) * (z2 - z1)));
}

bool CollisionBetweenCircles(double x1, double y1, double r1, double x2, double y2, double r2)
{
    if ((((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1))) <= (r1 + r2) * (r1 + r2)) {
        return true;
    }
    else {
        return false;
    }
}

bool CollisionBetweenSpheres(double x1, double y1, double z1, double r1, double x2, double y2, double z2, double r2)
{ 
    if ((((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)) + ((z2 - z1) * (z2 - z1))) <= ((r1 + r2) * (r1 + r2))) {
        return true;
    }
    else {
        return false;
    }
}

double PointOfCollisionBetweenCircles_X(double x1, double r1, double x2, double r2)
{
    return ((x1 * r2) + (x2 * r1)) / (r1 + r2);
}

double PointOfCollisionBetweenSpheres_X(double x1, double r1, double x2, double r2)
{
    return ((x1 * r2) + (x2 * r1)) / (r1 + r2);
}

double PointOfCollisionBetweenCircles_Y(double y1, double r1, double y2, double r2)
{
    return ((y1 * r2) + (y2 * r1)) / (r1 + r2);
}

double PointOfCollisionBetweenSpheres_Y(double y1, double r1, double y2, double r2)
{
    return ((y1 * r2) + (y2 * r1)) / (r1 + r2);
}

double PointOfCollisionBetweenSpheres_Z(double z1, double r1, double z2, double r2)
{
    return ((z1 * r2) + (z2 * r1)) / (r1 + r2);
}

double PointOfIntersectionBetweenLines_X(double Ax, double Ay, double Bx, double By, double Cx, double Cy, double Dx, double Dy)
{
    double divisor = ((Ax - Bx)*(Cy - Dy) - (Ay - By)*(Cx - Dx));
    if (divisor == 0) {
        return INFINITY;
    }
    double dividendX = ((Ax*By - Ay*Bx)*(Cx - Dx) - (Ax - Bx)*(Cx*Dy - Cy*Dx));
    if (dividendX == 0) {
        return NAN;
    }
    return dividendX / divisor;
}

double PointOfIntersectionBetweenLines_Y(double Ax, double Ay, double Bx, double By, double Cx, double Cy, double Dx, double Dy)
{
    double divisor = ((Ax - Bx)*(Cy - Dy) - (Ay - By)*(Cx - Dx));
    if (divisor == 0) {
        return INFINITY;
    }
    double dividendY = ((Ax*By - Ay*Bx)*(Cy - Dy) - (Ay - By)*(Cx*Dy - Cy*Dx));
    if (dividendY == 0) {
        return NAN;
    }
    return dividendY / divisor;
}

bool CollisionPointInRectLT(double pX, double pY, double rectLeft, double rectTop, double rectWidth, double rectHeight)
{
    if (pX >= rectLeft && pX <= (rectLeft + rectWidth) && pY >= rectTop && pY <= (rectTop + rectHeight)) {
        return true;
    }
    else {
        return false;
    }
}

bool CollisionPointInRect(double pX, double pY, double rectCenterX, double rectCenterY, double rectWidth, double rectHeight)
{
    if (pX >= rectCenterX - (rectWidth * 0.5) && pX <= rectCenterX + (rectWidth * 0.5) && pY >= rectCenterY - (rectHeight * 0.5) && pY <= rectCenterY + (rectHeight * 0.5)) {
        return true;
    }
    else {
        return false;
    }
}

bool CollisionRectInRect(double rect1Left, double rect1Top, double rect1Right, double rect1Bottom, double rect2Left, double rect2Top, double rect2Right, double rect2Bottom)
{
    if (rect1Left <= rect2Right && rect2Left <= rect1Right && rect1Top <= rect2Bottom && rect2Top <= rect1Bottom) {
        return true;
    }
    else {
        return false;
    }
}

double PostCollisionVelocity(double u1, double u2, double m1, double m2, double CoR)
{
    double v1 = ((u1 * (m1 - m2)) + (2 * m2 * u2)) / (m1 + m2);
    return v1 * CoR;
}

double RandomNumber(int lowest, int highest, int decimalPlaces, bool preventZero)
{
    srand((unsigned int)time(NULL));
    double decimal = 0;
    int decimalRange = (int)(pow(10, decimalPlaces));
    if (decimalPlaces > 0) {
        decimal = (rand() % decimalRange);
        decimal = decimal / decimalRange;
    }
    if (lowest == highest) {
        return lowest;
    }
    else {
        if (lowest > highest) {
            int tempValue = lowest;
            lowest = highest;
            highest = tempValue;
        }
        double returnValue = lowest + rand() % (highest - lowest) + decimal;
        if (preventZero == true && returnValue == 0) {
            return RandomNumber(lowest, highest, decimalPlaces, preventZero);
        }
        else {
            return returnValue;
        }
    }
}

Please delete the following files/folder for a fresh update:
B4X:
<file>   config.txt
<folder> workspace
<folder> project
 
Last edited:
Top