Native Extensions

I try to work with alredy builded classes.jar by unity https://github.com/Unity-Technologies/unity-ads-android/releases/download/2.1.0/unity-ads.zip
It works without any problem with JNI, but for callbacks I need to create my own java classes with custom code using the same classes.jar.

When I try to
import com.unity3d.ads.UnityAds;

I recieve an error that package com.unity3d.ads does not exist.

Hereā€™s a small update from the native extension support.
Weā€™ve added support for HTML5 and we anticipate it being shipped in the 1.2.105 release.

As you might be aware, we are using Emscripten to generate our Html5 builds from C++. So, youā€™ll be able to use C++, JavaScript and JavaScript libraries which is Emscriptens glue between C++ and JavaScript.

Youā€™ll be able to make function calls in both directions (C++ <-> JavaScript) and here is a screen shot of the simple example app, demonstrating the features:

11 Likes

We have now deployed a new build server with fixes related to Java import errors. :slight_smile:

5 Likes

ā€œSmall updateā€? This is awesome! When is the .105 release scheduled for? Weā€™re still on .103, right?

7 Likes

Hopefully, the 1.2.104 should be released tomorrow, and the 105 release is scheduled for May 29ā€™th.
(I still have some code cleanup and code reviews to go through :wink: )

8 Likes

Cool! All works good! Thank you!

6 Likes

This is osom! I wonder who;d be the first with a Defold instant game on the Facebook =]

3 Likes

I would love to - but i think instant games is still only for selected companies?

I think I tried to sign up for that before but never heard back from Facebook. Just tried the form to sign up again and itā€™s giving an error. ĀÆ\_(惄)_/ĀÆ

2 Likes

thereā€™s a King power. Please reach out to me at oleg.pridiuk@king.com and I shall make the intro into FB so you get hooked up with FB instant games.

2 Likes

Another small updateā€¦

Iā€™ve cleaned up our AdMob example and itā€™s now published online:

It works on iOS and Android, for Banners, Interstitials, Rewarded Videos and Native Express ads.

Note that there is one (quite big) known issue for Banners on iOS: I got a crash when deleting the banners. Iā€™ve reported it as an issue to the Firebase (AdMob) team, and they are helping me debug it.

It is designed to work as a Defold library, so you can add it as a dependency.

Again, itā€™s designed as a starting example, but it should still work for most people.

We hope youā€™ll like it!
/The Defold team

15 Likes

Thank you right in the time when i need it :smiley:

3 Likes

Nice! Take it for a spin and let us know how it works out for you!

2 Likes

Some small news, weā€™ve finally started on the Windows support for Native Extensions! \o/

Have a nice weekend! :beers: :sunny: :tropical_drink: :sunglasses:

8 Likes

Hi @sven , @Mathias_Westerdahl I have an issue and I wasted a whole day trying to understand whats wrongā€¦ andā€¦ nothingā€¦
I really need your help.
Did you try to use callbacks with android native extensions?
I have a problem with my DefUnityAds extension on Android (On iOS it works without any problems)

It crashes in situation when I try to recieve few callbacks.
It is easy to reproduce with standart DefUnityAds example:

  • just run an example on android
  • then tap to Initialize button
  • then fast tap 2-3 times to ShowAd button.

On iOS it receives few errors by callback - it is internal error of ads skd like ā€œnot initializedā€ and so onā€¦ itā€™s ok.
But on Android it crashes.

The crash is in lua part, something like:

Build fingerprint: 'Xiaomi/nikel/nikel:6.0/MRA58K/V8.2.1.0.MBFMIDL:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 14358, tid: 14373, name: Thread-13844  >>> com.agulev.test <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: '../src/gameobject/comp_script.cpp:212: dmGameObject::UpdateResult dmGameObject::CompScriptUpdate(const dmGameObject::ComponentsUpdateParams&): assertion "top == lua_gettop(L)" failed'
    r0 00000000  r1 00003825  r2 00000006  r3 f342c978
    r4 f342c980  r5 f342c930  r6 00000000  r7 0000010c
    r8 ee91e1d0  r9 f342c56c  sl 00000000  fp eea001b0
    ip 00000006  sp f342c4d8  lr f7184ebd  pc f71872ac  cpsr 400e0010

backtrace:
    #00 pc 000432ac  /system/lib/libc.so (tgkill+12)
    #01 pc 00040eb9  /system/lib/libc.so (pthread_kill+32)
    #02 pc 0001c81b  /system/lib/libc.so (raise+10)
    #03 pc 000199cd  /system/lib/libc.so (__libc_android_abort+34)
    #04 pc 00017580  /system/lib/libc.so (abort+4)
    #05 pc 0001b42f  /system/lib/libc.so (__libc_fatal+16)
    #06 pc 00019a55  /system/lib/libc.so (__assert2+20)
    #07 pc 000c6b2c  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_ZN12dmGameObject16CompScriptUpdateERKNS_22ComponentsUpdateParamsE+212)
    #08 pc 000b5d90  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_ZN12dmGameObject6UpdateEPNS_10CollectionEPKNS_13UpdateContextE+764)
    #09 pc 0009ecfc  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_ZN8dmEngine4StepEPNS_6EngineE+1268)
    #10 pc 00101e5c  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_ZN10dmGraphics18RunApplicationLoopEPvPFvS0_EPFiS0_E+20)
    #11 pc 000a152c  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_ZN8dmEngineL7InitRunEPN15dmEngineService13EngineServiceEiPPcPFvPNS_6EngineEPvES9_S7_+168)
    #12 pc 000a15cc  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_ZN8dmEngine6LaunchEiPPcPFvPNS_6EngineEPvES6_S4_+72)
    #13 pc 0009d964  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_Z11engine_mainiPPc+112)
    #14 pc 0009bcb4  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (main+24)
    #15 pc 0023cb9c  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (_glfwPreMain+236)
    #16 pc 0009bcdc  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (android_main+20)
    #17 pc 0023d3bc  /data/app/com.agulev.test-1/lib/arm/libDefUnityAds.so (android_app_entry+176)
    #18 pc 000407bb  /system/lib/libc.so (_ZL15__pthread_startPv+30)
    #19 pc 0001a051  /system/lib/libc.so (__start_thread+6)

It is almost all time assertion problem but in different places.

I thougth that the problem is in my code, but:

  1. It works perfect on iOS;
  2. Second strange thing, I made few logs:
    dmLogInfo("top %i",top);
    lua_rawgeti(L, LUA_REGISTRYINDEX, defUtoLua->listener.m_Callback);
   	lua_rawgeti(L, LUA_REGISTRYINDEX, defUtoLua->listener.m_Self);
   	lua_pushvalue(L, -1);
    dmLogInfo("top1 %i",lua_gettop(L));
    dmScript::SetInstance(L);
    dmLogInfo("top2 %i",lua_gettop(L));
    lua_pushnumber(L, type_of_msg);
    dmLogInfo("top3 %i",lua_gettop(L));
    int count_table_elements = 1;
    if (key_2 != NULL){
        count_table_elements = 2;
    }
    lua_createtable(L, 0, count_table_elements);
    dmLogInfo("top4 %i",lua_gettop(L));
    luaL_push_pair_str_str(L, key_1, value_1);
    if (key_2 != NULL){
        luaL_push_pair_str_num(L, key_2, value_2);
    }
    dmLogInfo("top5 %i",lua_gettop(L));
    int ret = lua_pcall(L, 3, LUA_MULTRET, 0);
    dmLogInfo("top6 %i",lua_gettop(L));
    if (ret != 0) {
        dmLogError("Error running defUtoLua callback: %s", lua_tostring(L, -1));
        lua_pop(L, 1);
    }
    dmLogInfo("top7 %i",lua_gettop(L));

and receive next result:

INFO:DEFAULT: top 0
INFO:DEFAULT: top1 3
INFO:DEFAULT: top2 5 --between top1 and top2 only dmScript::SetInstance(L); - WHY STACK IS SO BIG? O_o
INFO:DEFAULT: top3 1
INFO:DEFAULT: top4 2
INFO:DEFAULT: top5 2

the same trace is on ios almost all time

INFO:DEFAULT: top1 3
INFO:DEFAULT: top2 2
INFO:DEFAULT: top3 3
INFO:DEFAULT: top4 4
INFO:DEFAULT: top5 4

On iOS I have stable trace of stack size all the time.
On Android first and second time - itā€™s ok, but after then it randomly changes size of stack (it is not all time place between top1 and top2).
It looks like something changing stack in other thread or something like this. I canā€™t explain and canā€™t solve this problem (

Sorry for this long post, I hope you understand what I mean.
I reread all c++/lua docs, recheck all methods and ask @britzl about lua_gettop ā€¦ Nothing helpsā€¦

Hope you can help me, thank you.

1 Like

Well, to answer your first question, yes, we use callbacks in the AdMob example: googlemobileads.cpp

As for the discrepancy in the stack, Iā€™m not sure, Iā€™m going to read through your code when I get home tonight.
But, a tip, is to make sure you push/pop the number of expected values in each function.
See the documentation for DM_LUA_STACK_CHECK() and examples here and here

Also, sometimes when forgetting to return the correct value (number of values pushed onto the stack) from the function, it can also misbehave (e.g. crash)

1 Like

You call that small news? This is awesome!

3 Likes

Looks like I am right and the issue is in multithreading.

I see that you solved the same issue using array of MessageCommand (your own stack of callbacks) - it looks like a plan.

Iā€™ll try to make something like this in my native extension, thank you!

I was bewildered because the same code works good on ios. But on ios all callbacks works using dispatch_async(dispatch_get_main_queue() ā€¦ (in SDK) and i think that the reason why it works without any problem.
But strange that on Android all callbacks run with runOnUiThread methods (in SDK), but it not helps.

Iā€™ll try to check thread ids and understand why it not helps.

UPD:
I made stack of callbacks and push them to lua by update method. All works fine. Thank you @Mathias_Westerdahl for the help

3 Likes

Great that you got it working!
Yes, the threading bit is important when dealing with activities. Iā€™m not sure why your runOnUiThread didnā€™t work though, I know we use it in the engine for the same purpose. And, from the Android doc:

ā€œthe main thread is also sometimes called the UI thread.ā€

2 Likes

I donā€™t know too, this code into SDK (not my, it is Unity code).
I tried to run callbacks on my side using runOnUiThread and using the main looper (context.getMainLooper) - same result.

As faster and most efficien variand I choosed variant from your example, when you send all callbacks in udate method.