4

I started re-writing my Function Plotter which takes mathematical function and calculates a y value for a given x. To re-write it, I want to dynamically create a method using IL. The test IL code that I have now uses 2 LocalBuilders and multiplies them. However, when i return the value, i receive(what seems to be) a random number instead of the real answer.

Here's the following code that I've been using.

        ILGenerator il = hello.GetILGenerator();

        LocalBuilder a = il.DeclareLocal(typeof(int));
        LocalBuilder b = il.DeclareLocal(typeof(int));
        LocalBuilder multOfAandB = il.DeclareLocal(typeof(int));

        il.Emit(OpCodes.Ldc_I4, 5); // Store "5" ...
        il.Emit(OpCodes.Stloc, a);  // ... in "a".

        il.Emit(OpCodes.Ldc_I4, 6); // Store "6" ...
        il.Emit(OpCodes.Stloc, b);  // ... in "b".

        il.Emit(OpCodes.Ldloc, a);
        il.Emit(OpCodes.Ldloc, b); 

        il.Emit(OpCodes.Mul);       // Multiply them ...
        il.Emit(OpCodes.Ret);       // ... and return the result.

This should return 30 but currently I'm receiving 4.2038953929744512E-44. Is there something wrong with my code thats causing the function to return the wrong value?

Thanks in advance

EDIT

The code calling the function is as follows:

        object[] invokeArgs = { 42 };
        object obj = func.helloMethod.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us"));

and in my class where I store the function to later call it from func.helloMethod has a DynamicMethod which is defined as follows:

DynamicMethod hello = new DynamicMethod("Hello",
            typeof(double),
            helloArgs,
            typeof(double).Module);
Felix
  • 99
  • 2
  • 10
  • looks fine... how are you retrieving and showing the result (especially what becomes of `multOfAandB`?), I'd suspect a problem with the execution rather than with that part of the code. The random number will be uninitialized memory. – Cee McSharpface Jan 16 '17 at 19:11
  • @dlatikay from my main I'm calling 'object[] invokeArgs = { 42 }; object obj = func.helloMethod.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us"));' where my dynamic method is ' DynamicMethod hello = new DynamicMethod("Hello", typeof(double), helloArgs, typeof(double).Module); ' I'm saving my DynamicMethod in a public variable which i call from my main+ – Felix Jan 16 '17 at 19:14
  • can we assume that the rest of the calling code is built similar to [this](https://msdn.microsoft.com/en-us/library/csx7wsz2(v=vs.110).aspx); and your 42 is never Ldarg_0'ed - still suspecting a caller/callee issue here – Cee McSharpface Jan 16 '17 at 19:18
  • @dlatikay the code that I'm using is based on http://stackoverflow.com/questions/15278566/emit-local-variable-and-assign-a-value-to-it – Felix Jan 16 '17 at 19:19
  • 1
    ok... we'll have to focus on the calling code. for example that `typeof(double)` is suspect, would it not rather be int? please edit that outer calling code into your question, maybe me or someone else is able to spot the problem there. – Cee McSharpface Jan 16 '17 at 19:23
  • @dlatikay changing it to typeof(int) solved the problem. I didn't know that IL was so sensitive about the return type. – Felix Jan 16 '17 at 19:31

2 Answers2

3

You seem to accidentially coerce the return value from int to double. Dynamic execution is surprisingly fault-tolerant here, there seems to be no check for type mismatch.

Change the calling code to match the data types of the internal locals:

var hello = new DynamicMethod(
    "Hello",
    typeof(int),
    helloArgs,
    typeof(YourClassNameHere).Module
);

Note that the type in the last argument should be your class name, not that of the argument data type.

Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77
  • The CLR is a size queen. It cares more about the size of variables than their type (unless you're doing a virtual method call, but even then...) – hoodaticus Jan 24 '17 at 15:44
1

The problem here was the definition of the DynamicMethod:

DynamicMethod hello = new DynamicMethod("Hello",
        typeof(double),
        helloArgs,
        typeof(double).Module);

Since 6 * 5 returns 30, which is an int, it had problems changing the int to a double and returned the wrong answer. Once I changed it to typeof(int), the returned value was 30. I had no idea that IL was so particular on the type.

Felix
  • 99
  • 2
  • 10