Hi,

Anyone about this??
if I run "mono_domain_unload(domain);"
and after do
assembly = mono_assembly_load_from_full(image, referenceName, &status, FALSE); it is not working properly if referenceName is kept from one launch to the next...
I think the code bellow is showing it... or am I doing something wrong??
may be it is linked to the "[DllImport ("__Internal"..." which blocking the unloading of the assembly?

And a question: Is there a way to debug a running assembly (embeded)?
On python and lua, you can register a function that is called on every line executed... I totally understand it is different for mono, but what are my options? where can I find documentations about debugging from and embedding application?

Thanks,
Pierre

The source to test is (mono_test.c):
/******************************************************************************************************************/
#include <mono/jit/jit.h>

#include <mono/metadata/mono-config.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/mono-gc.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/mono-debug.h>
#include <mono/utils/mono-logger.h>



/**********************************************************************************/
/* */
/**********************************************************************************/
#define TRUE  1
#define FALSE 0
#define BYTE unsigned char
#define gMalloc malloc
#define gFree free

BYTE *readFile(FILE *f, size_t *size)
{
  BYTE *buffer;
  size_t i;

  fseek(f, 0, SEEK_END);
  *size = ftell(f);
  fseek(f, 0, SEEK_SET);

  buffer = (BYTE *) gMalloc(*size);
  if(buffer == NULL) return NULL;

  i = fread(buffer, 1, *size, f);
  if(i != *size)
  {
    gFree(buffer);
    return NULL;
  }
  return buffer;
}


/**********************************************************************************/
/* */
/**********************************************************************************/
static MonoDomain *rootDomain;
static MonoDomain *domain;
static MonoImage *image;
static MonoAssembly *assembly;




/**********************************************************************************/
/* */
/**********************************************************************************/
__declspec(dllexport) void mono_report(char* str)
{
  printf("%s\n", str);
}


/**********************************************************************************/
/* */
/**********************************************************************************/
static int monoScriptCompile(char *fileName, char *referenceName)
{

  int res;
  char *ret, *strErr, *str;
  char buffer[256];
  FILE *f;
  BYTE *data;
  size_t dataLen;
  MonoImageOpenStatus status;
  MonoAssemblyName *aName;


  if(domain != NULL)
  {
    res = mono_domain_set(rootDomain, FALSE);
    if(!res)
    {
      printf("Failed to set root domain\n");
      return FALSE;
    }

    mono_domain_unload(domain);
    mono_gc_collect(mono_gc_max_generation());
  }
  domain = NULL;
  image = NULL;
  assembly = NULL;


  domain = mono_domain_create_appdomain("ScriptSubDomain", NULL);
  res = mono_domain_set(domain, FALSE);
  if(!res)
  {
    printf("Failed to set domain\n");
    return FALSE;
  }

  sprintf(buffer, "%s.dll", fileName);
  f = fopen(buffer, "rb");
  if(f == NULL)
  {
    printf("Cannot open file: %s\n", buffer);
    return FALSE;
  }
  data = readFile(f, &dataLen);
  fclose(f);




    // open the assembly from the data we read, so we never lock files
  image = mono_image_open_from_data_with_name(data, dataLen,
                                              TRUE /* copy data */,
&status,
                                              FALSE /* ref only */,
referenceName);
  gFree(data);
  if (status != MONO_IMAGE_OK || image == NULL)
  {
    printf("Cannot create image from data\n");
    return FALSE;
  }

    // load the assembly
  assembly = mono_assembly_load_from_full(image, referenceName, &status, FALSE);
  if (status != MONO_IMAGE_OK || assembly == NULL)
  {
    printf("failed to load assembly\n");
    mono_image_close(image);
    return FALSE;
  }

  aName = mono_assembly_get_name(assembly);
  printf("Assembly Name: %s\n", mono_stringify_assembly_name(aName));

  res = mono_domain_set(rootDomain, FALSE);

  return TRUE;
}



/**********************************************************************************/
/* */
/**********************************************************************************/
static int monoScriptRun(void)
{
  int res, base;
  char *ret, *strErr;
  MonoMethodDesc* monoMethodDesc;
  MonoMethod* method;
  MonoObject *exception;


  if(domain == NULL || assembly == NULL)
  {
   printf("Run Failed: Not compiled\n");
    return FALSE;
  }

  if (!mono_domain_set(domain, FALSE))
  {
    printf("Run Failed: set domain failed\n");
    return FALSE;
  }

  monoMethodDesc = mono_method_desc_new("Script:Main", 0);
  if(monoMethodDesc == NULL)
  {
    printf("mono_method_desc_new failed\n" );
    return FALSE;
  }

  //Search the method in the image
  method = mono_method_desc_search_in_image(monoMethodDesc, image);
  mono_free(monoMethodDesc);
  if(method == NULL)
  {
    printf("mono_method_desc_search_in_image failed\n");
    return FALSE;
  }

  //run the method
  exception = NULL;
  mono_runtime_invoke(method, NULL, NULL, &exception);
  if(exception != NULL)
  {
    printf("An exception was thrown when calling Script:Main!\n");
    return FALSE;
  }

  res = mono_domain_set(rootDomain, FALSE);

  return TRUE;
}


/**********************************************************************************/
/* */
/**********************************************************************************/
static void monoInit(void)
{
  if(rootDomain == NULL)
  {
    mono_set_dirs("C:\\Program Files\\Mono\\lib",
                  "C:\\Program Files\\Mono\\etc");
    rootDomain = mono_jit_init("ScriptEngine");

    mono_thread_set_main(mono_thread_current());
  }
}



/**********************************************************************************/
/* */
/**********************************************************************************/
int main(int argc, char **argv)
{
  mono_report("Starting");
  monoInit();
  monoScriptCompile("code1", "code.dll");
  monoScriptRun();
  monoScriptCompile("code2", "code.dll");
  monoScriptRun();
  monoScriptCompile("code2", "code2.dll");
  monoScriptRun();
}
/******************************************************************************************************************/



The cs source (code1.cs) for the first ddl (compiled with mcs code1.cs -target:library):
/******************************************************************************************************************/
using System;
using System.Runtime.InteropServices;

public class ScriptEngine
{
[DllImport ("__Internal", EntryPoint="mono_report")]
static extern public void report (String str);
}

public class Script
{
  static void Main ()
  {
    ScriptEngine.report("Code 1");
  }
}
/******************************************************************************************************************/


The cs source(code2.cs) for the second ddl (compiled with mcs code2.cs -target:library):
/******************************************************************************************************************/
using System;
using System.Runtime.InteropServices;

public class ScriptEngine
{
[DllImport ("__Internal", EntryPoint="mono_report")]
static extern public void report (String str);
}



public class Script
{
  static void Main ()
  {
    ScriptEngine.report("Code 2");
  }
}
/******************************************************************************************************************/



On 13/02/2018 18:22, pierre wrote:
Here a sample in one (dirty) c file...
the file can be compiled easily, just adding the mono library and the mono include path.

the core is doing:

      monoScriptCompile("code1", "code.dll");
      monoScriptRun();
      monoScriptCompile("code2", "code.dll");
      monoScriptRun();
      monoScriptCompile("code2", "code2.dll");
      monoScriptRun();

And the result on my system is:

    Starting
    Assembly Name: code1, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    Code 1
    Assembly Name: code1, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    *Code 1*
    Assembly Name: code2, Version=0.0.0.0, Culture=neutral,
    PublicKeyToken=null
    Code 2

and as you can see, the code is not reloaded properly when the reference is kept, but reloaded in the second case!!!


On 13/02/2018 14:15, R Zaghi wrote:
Just for the record, I mean write it in a C# class and load that one class so you can handle everything in C# itself - much more robust.


On Tue, 13 Feb 2018 at 19:04, R Zaghi <rza...@mosaic3dx.com <mailto:rza...@mosaic3dx.com>> wrote:

    If this is actually a problem with a library like mono then it
    sounds like a caching problem. If you build mono from source then
    it's easier to look into this...

    Compare your code with this example. In the example, the .dll
    assembly is re-loaded in a loop. You can see the clean up portion
    and the shutdown or initialisation portions too:

    https://github.com/ramin-zaghi/mono-embedding

    Regarding how to compile code at runtime without a system() call,
    you can use CodeDom (look it up) to compile from files, or in a
    mono-specific way use Mono Compiler Service (e.g the Evaluator
    and CompilerContext classes - google them) which allow you to
    evaluate partial expressions/statements/etc.

    I use both depending on situation and they work pretty well.
    Roslyn is apparently another option but let's not go there :)

    R.





    On Tue, 13 Feb 2018 at 16:17, pierre
    <pierre.saun...@ppmodeler.com
    <mailto:pierre.saun...@ppmodeler.com>> wrote:

        Thanks for the answer.


        > you 100% sure the old files are all overwritten?
        Yes, I have checked the file time... and also included a

            remove(fileName);

        to be sure!


        >There are a couple of different ways to get compiled binary
        at runtime without a system() call
        Which ones?

        I have tried something:
        calling mono_image_open_from_data_with_name and
        mono_assembly_load_from_full with a different file name on
        every compile and it is working!!!

        so, the following code is not reloading properly:

            monoEngine->fileName = strdup("code.dll");


            monoEngine->image =
            mono_image_open_from_data_with_name(data, dataLen,
            TRUE /* copy data */,
            &status,
            FALSE /* ref only */,
            monoEngine->fileName);
            if (status != MONO_IMAGE_OK || monoEngine->image == NULL)
            {
            }
            monoEngine->assembly =
            mono_assembly_load_from_full(monoEngine->image,
            monoEngine->fileName,
            &status, FALSE);
            if (status != MONO_IMAGE_OK || monoEngine->assembly == NULL)
            {
            }


        but, the same with a different file name on every run (only
        the monoEngine->fileName creation differ) is working:

            static int version = 1;
            ...

            sprintf(monoEngine->fileName, "code%03d.dll", version);
            version ++;


            monoEngine->image =
            mono_image_open_from_data_with_name(data, dataLen,
            TRUE /* copy data */,
            &status,
            FALSE /* ref only */,
            monoEngine->fileName);
            if (status != MONO_IMAGE_OK || monoEngine->image == NULL)
            {
            }
            monoEngine->assembly =
            mono_assembly_load_from_full(monoEngine->image,
            monoEngine->fileName,
            &status, FALSE);
            if (status != MONO_IMAGE_OK || monoEngine->assembly == NULL)
            {
            }

        Is there a wait to be introduced after a mono_domain_unload?
        It is like doing mono_domain_unload,
        mono_image_open_from_data_with_name and
        mono_assembly_load_from_full with the same file name is
        detected and the unload is not performed....


        > This is more likely to be a problem outside of mono.
        I do agree... but I am running out of idea on why!!!


        and for mono_method_desc_search_in_image? is it bug?


        Pierre


        On 13/02/2018 07:15, R Zaghi wrote:
        I think we need to know a bit more about what you are doing
        in the code exactly but as a quick first guess if you are
        recompiling using a system() call then are you 100% sure the
        old files are all overwritten? There are a couple of
        different ways to get compiled binary at runtime without a
        system() call which I prefer but if you are using a system()
        call then have you tried two separate calls with two
        parallel binaries loaded as a start to debug your code?

        This is more likely to be a problem outside of mono.

        Ramin




        Ramin Zaghi

        *Mosaic3DX™ | User Interface Technology*
        St John's Innovation Centre,
        Cowley Road,
        Cambridge,
        CB4 0WS, UK*
        *
        *E*:**rza...@mosaic3dx.com <mailto:rza...@mosaic3dx.com>
        *T*: +44 1223 421 311 <tel:+44%201223%20421311>
        http://linkedin.com/in/raminzaghi



        On Tue, 13 Feb 2018 at 01:27, pierre
        <pierre.saun...@ppmodeler.com
        <mailto:pierre.saun...@ppmodeler.com>> wrote:

            Hi,

            I am trying to embed mono... and I ran into a problem
            with the code:

                monoMethodDesc = mono_method_desc_new("Script:Main", 0);
                method =
                mono_method_desc_search_in_image(monoMethodDesc,
                monoEngine->image);


            It is returning a method on the cs code:

                public class Script
                {
                  static public void Main ()
                  {
                ScriptEngine.report("--Main Called ");
                  }
                }


            but it is also returning a method on the cs code (with
            the wrong class name):

                public class Script*2*
                {
                  static public void Main ()
                  {
                ScriptEngine.report("--Main Called ");
                  }
                }

            while it should only return for:

                monoMethodDesc =
                mono_method_desc_new("Script2:Main", 0);


            Am i doing something wrong or is this a bug? It seem
            that mono_method_desc_search_in_image is returning a
            value if the actual class name is starting with the
            given  class name.... so, the same method is returned if
            I look for "Script:Main" but the declared class is
            "Script:Main", "Script_test:Main" or "Script2:Main"...

            and a question:
            is there a way to know if mono_domain_unload was
            successful or not?

            I am creating an app domain per script so that I can
            recompile and reload the script at will...
            I do not detect any error, but the new script seems not
            to replace the old one...
            Basically, I am doing:

                res = mono_domain_set(rootDomain, FALSE);
                mono_domain_unload(monoEngine->domain);
                monoEngine->domain =
                mono_domain_create_appdomain("ScriptEngine-sub", NULL);

                data = readFile(f, &dataLen);
                fclose(f);
                monoEngine->image =
                mono_image_open_from_data_with_name(data, dataLen,
                TRUE /* copy data */,
                &status,
                FALSE /* ref only */,
                monoEngine->fileName);
                  free(data);
                  if (status != MONO_IMAGE_OK || monoEngine->image
                == NULL)
                  {
                    return FALSE;
                  }

                    // load the assembly
                  monoEngine->assembly =
                mono_assembly_load_from_full(monoEngine->image,
                monoEngine->fileName,
                &status, FALSE);
                  if (status != MONO_IMAGE_OK ||
                monoEngine->assembly == NULL)
                  {
                mono_image_close(monoEngine->image);
                    return FALSE;
                  }

            but it does not seem to work. The code that runs is
            always the first loaded one!!

            I also added the following code to my engine:

                mono_trace_set_log_handler(monoLogCallback, NULL);
                mono_trace_set_print_handler(monoPrintCallback);
                mono_trace_set_printerr_handler(monoPrintCallback);
                mono_trace_set_level_string ("debug");


            but it is reporting debug info only on the first run...
            is there a way to having it working on every run?

            Lastly, Is there a way to compile cs source without
            launching a

                system("msc.code.cs -target:library");

            thanks in advance

            Pierre



            _______________________________________________
            Mono-list maillist  -mono-l...@lists.dot.net 
<mailto:mono-l...@lists.dot.net>
            http://lists.dot.net/mailman/listinfo/mono-list

            _______________________________________________
            Mono-devel-list mailing list
            Mono-devel-list@lists.dot.net
            <mailto:Mono-devel-list@lists.dot.net>
            http://lists.dot.net/mailman/listinfo/mono-devel-list

--


        Ramin Zaghi

        *Mosaic3DX™ | User Interface Technology*
        St John's Innovation Centre,
        Cowley Road,
        Cambridge,
        CB4 0WS, UK*
        *
        *E*:**rza...@mosaic3dx.com <mailto:rza...@mosaic3dx.com>
        *T*: +44 1223 421 311
        http://linkedin.com/in/raminzaghi


--


    Ramin Zaghi

    *Mosaic3DX™ | User Interface Technology*
    St John's Innovation Centre,
    Cowley Road,
    Cambridge,
    CB4 0WS, UK*
    *
    *E*:**rza...@mosaic3dx.com <mailto:rza...@mosaic3dx.com>
    *T*: +44 1223 421 311
    http://linkedin.com/in/raminzaghi

--



Ramin Zaghi

*Mosaic3DX™ | User Interface Technology*
St John's Innovation Centre,
Cowley Road,
Cambridge,
CB4 0WS, UK*
*
*E*:**rza...@mosaic3dx.com <mailto:rza...@mosaic3dx.com>
*T*: +44 1223 421 311
http://linkedin.com/in/raminzaghi



_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.dot.net
http://lists.dot.net/mailman/listinfo/mono-devel-list

Reply via email to