Build ICE 3.7.1 with option MANAGED=yes on macOS (or Windows)

Thor_42Thor_42 Member Thorsten BuxOrganization: PersonalProject: Connect Unity app with Raspberry Pi targeting Android

Hi,

I try to run a Unity3D app (Mono) on an Android device. The Unity3D app contains ICE 3.7 (3.7.1) for .NET. I found this old forum post: https://forums.zeroc.com/discussion/5730/ice-on-mono-on-android which pointed me to build ICE with with the option MANAGED = yes. Not I try to build the latest ICE release 3.7.1 on macOS but I can't find the MANAGED option.

(And the build on Windows fails with error: fatal error C1083: Cannot open include file: 'stdlib.h': No such file or directory)

I'm following the instructions here: https://github.com/zeroc-ice/ice/tree/3.7/csharp but can't see how to set the MANAGED option and couldn't find anything in the ICE documentation.

Best Answer

Answers

  • xdmxdm La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    The MANAGED option is no longer relevant as Ice 3.7. UNITY 2018.1 include support for netcore2.0, so you should be able to use the nestandard2.0 binaries included with zeroc.ice.net NuGet package or build your own using .NET Core

    Regarding the windows build failure seems that you have not installed the C++ SDK required to build the slice2cs Slice compiler. Try installing Windows 10 SDK (10.0.10240.0) from Visual Studio 2017 setup.

  • philip_lambphilip_lamb Christchurch, New ZealandMember Philip Lamb
    edited May 2018

    Thorsten and I are working together on this project. The background to the issue is that our Ice app which works fine using Ice C++ and and Ice C# inside the Unity 3D editor fails when deployed as part of a Unity app on Android.

    We're able to attach to the running app on Android and this is where the failure occurs:

    Our Ice interface is PiTrackerServer and we are invoking method setTrackerOptionFloat(int, float) on it, but if we don't hit the exception here we hit it in some other method getting or setting float values.

    In the debugger we can see that _valBytes is correctly interpreted as floatVal 0.25, which is what we set: . Also we see that in this context _position=70 and _bytes is of size 240.

    but p doesn't show a legitimate value in the debugger (perhaps because of the fixed context?):

    At this stage, we're at a bit of a loss as to what to try next.

  • xdmxdm La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff

    Hi Philip,

    I have try to reproduce the issue with a Xamarin project running on Android, as far as I know it uses the same mono run-time that Unity, and sending a float doesn't cause any problems would be nice if you can provide a small sample project that allow us to reproduce the issue.

    You can also try to patch Ice.dll to not require using unsafe code, you can check the old code in our 3.6 branch https://github.com/zeroc-ice/ice/blob/3.6/csharp/src/Ice/ByteBuffer.cs

  • xdmxdm La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    edited June 2018

    Hi,

    I did some more testing with Unity 2018.1

    //Slice
    module Demo
    {
    interface Hello
    {
    void sendFloat(float f);
    }
    }
    

    I drop zeroc.ice.net\3.7.1\lib\netstandard2.0\Ice.dll and C# generated code into the project assets Then I attach this script:

    using UnityEngine;
    
    public class NewBehaviourScript : MonoBehaviour {
    
        private Ice.Communicator communicator;
    
        // Use this for initialization
        void Start () {
            communicator = Ice.Util.initialize();
        }
    
        public void sendFloat(){
            var prx = Demo.HelloPrxHelper.uncheckedCast(
                communicator.stringToProxy("hello:tcp -h 192.168.1.46 -p 10000"));
            prx.sendFloat(0.25f);
        }
    }
    
    

    I run this on my android device and the C# server correctly receives the float value 0.25

    In the player settings I select

    Player Runtime Version: .NET 4.x Equivalent
    Scripting Backend: Mono
    API Compatibility Level: .NET 4.x
    

    It also works with API Compatibility Level: .NET Standard 2.0

  • Thor_42Thor_42 Member Thorsten BuxOrganization: PersonalProject: Connect Unity app with Raspberry Pi targeting Android

    I'll do some more tests. Thanks for your quick reply.

  • philip_lambphilip_lamb Christchurch, New ZealandMember Philip Lamb
    edited June 2018

    We're dealing with passing a struct like this:

    //Slice
    module MyModule
    {
        struct RowVec4 {float c0; float c1; float c2;  float c3; }
        struct Mtx3x4 {RowVec4 r0; RowVec4 r1; RowVec4 r2; }
        struct TimeStamp {long sec; int usec; }
        struct MyState {
            int uid;
            bool flag;
            Mtx3x4 mtx;
            TimeStamp time;
        }
        interface MyServer {
            idempotent MyState getMyState(int uid);
        }
    }
    

    Sending and receiving this struct from C# code running against Ice C# inside Unity 2018.1 works fine on macOS and iOS deployments from Unity, but crashes inside some unsafe code inside Ice on Android.

    A C# developer has suggested that Ice might not be correctly dealing with the differences in the way that .Net and Mono pack structures. He has suggested that we need to enforce 4-byte alignment on the bool and the following fields of the structure, but since this would be in Ice-generated code, I'm unsure where exactly we'd set this.

  • philip_lambphilip_lamb Christchurch, New ZealandMember Philip Lamb

    This SO answer suggests that the .Net CLR packs structs with non-trivial types differently from the way that the Mono runtime does: https://stackoverflow.com/a/24744714 .. might be relevant.

  • philip_lambphilip_lamb Christchurch, New ZealandMember Philip Lamb

    OK, we've managed to form this into a minimal test case and can reliably reproduce it from this test case. The attached archive contains a minimal project for a C++ server which implements getMyState (as above) and a Unity project which uses Ice C# to query it. In the Unity Editor, it runs fine, but when we run it in a deployed Android app (mono runtime), we get System.IndexOutOfRangeException, as shown in the image (captured in attached Visual Studio).

    Ice C++/C# 3.7.1.
    Unity 2018.1.2f1
    Android devices tested: Nexus 6 running Android 7.0, Nexus 5 running Android 6.0.1, and Galaxy S7 running Android 7.0

  • xdmxdm La Coruña, SpainAdministrators, ZeroC Staff Jose Gutierrez de la ConchaOrganization: ZeroC, Inc.Project: Ice Developer ZeroC Staff
    Accepted Answer

    Hi Philip,

    I was able to reproduce the problem and push a fix to remove the unsafe code used in ByteBuffer, see https://github.com/zeroc-ice/ice/commit/bb19cbea549261ba0aca8e1e7f138c4b905de648

  • philip_lambphilip_lamb Christchurch, New ZealandMember Philip Lamb

    Many thanks Jose. We've now recompiled Ice.dll and this addresses our problem.

  • Thor_42Thor_42 Member Thorsten BuxOrganization: PersonalProject: Connect Unity app with Raspberry Pi targeting Android

    Many thanks for your support and quick response, Jose. :)

Sign In or Register to comment.