AdrianPi's picture

null reference

Hello,

I'm dynamically loading and assembly wich in turns uses OpenTK. I needed to override AppDomain's AssemblyResolve to load the OpenTK assembly. However when I call any GL class function (GetString, for instance) I get a null reference exception ("Object not set to an instance of an object").

An OpenGL context is already created and active. ¿Do I need to initialize something?

Any help would be appreciated. Thanks in advance.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

Yes, please see this post: http://www.opentk.com/node/1258#comment-6862

If it is not possible to have OpenTK create the context, you will have to use reflection to call the equivalent of:

new OpenTK.Graphics.OpenGL.GL().LoadAll();

Both the GL constructor and the LoadAll method are non-public (hence the need for reflection). The next version of OpenTK will provide a better way to initialize the OpenGL bindings.

AdrianPi's picture

Thanks for your prompt reply.

I'm trying with this:

            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (a.FullName.Contains("OpenTK"))
                {
                    MessageBox.Show("OpenTK found"); <-- ok
                    assembly = a;
                }
            }
 
            Type type = assembly.GetType("OpenTK.Graphics.GL");
            MessageBox.Show((type != null).ToString(), "type"); <-- ok
            MessageBox.Show(type.ToString()); <--- ok
            MethodInfo mi = type.GetMethod("LoadAll");
            MessageBox.Show(mi.ToString()); <--- ok
            try
            {
                mi.Invoke(null, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Invoke Exception");
            }

But the exception "Exception has been thrown by the target of an invocation" is thrown.

¿Am I doing something wrong? ¿Why the "new" keyword in your snippet?

the Fiddler's picture

You need to create an instance of the GL class first. Check out Activator.CreateInstance.

AdrianPi's picture

Isn't GL a static class?

I added the call to the constructor:

Assembly assembly = null;
 
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (a.FullName.Contains("OpenTK"))
                {
                    MessageBox.Show("OpenTK found");
                    assembly = a;
                }
            }
 
            Type type = assembly.GetType("OpenTK.Graphics.GL");
            MessageBox.Show((type != null).ToString(), "type");
            MessageBox.Show(type.ToString());
 
            ConstructorInfo ci = type.GetConstructor(BindingFlags.Static | BindingFlags.NonPublic, null, new Type[0], null);
            MessageBox.Show((ci != null).ToString(), "ctor");
            MessageBox.Show(ci.ToString());
            try
            {
                ci.Invoke(null, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Ctor Exception");
            } 
 
            MethodInfo mi = type.GetMethod("LoadAll");
            MessageBox.Show(mi.ToString());
            try
            {
                mi.Invoke(null, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Invoke Exception");
            }

Still not luck and getting TargetInvocationException.

Sorry for the message boxes, but I found no better way to log errors inside an ActiveX control inside the ActiveX test container...

the Fiddler's picture

No, neither GL nor LoadAll() are static anymore. (They used to be several months ago, but they were modified so they can inherit from a common base class).

Try this:

object gl = ci.Invoke(null);
...
mi.Invoke(gl, null);
AdrianPi's picture

I get "Cannot create an instance of OpenTK.Graphics.GL because it is an abstract class.

I'll try a big refactor and create the rendering context on the .net side and not on the activex (C++)...

the Fiddler's picture

Alright.

I just want to say that this error message is pretty strange, as OpenTK does create instances of the GL class internally. Maybe you are using an older version of OpenTK? This needs 0.9.9-2b or 0.9.9-3 to work.

AdrianPi's picture

It's 0.9.9-3, release, downloaded yesterday. ¿Do you thinks downloading the sources and compiling it will help?

the Fiddler's picture

Ok, I can see the issue now. You are reflecting on OpenTK.Graphics.GL from OpenTK.Compatibility, while my code referred to OpenTK.Graphics.OpenGL.GL from core OpenTK.

If you are using OpenTK.Graphics.GL, you can simply call GL.LoadAll() without reflection.

Your reflection code should work correctly if you simply change typeof(OpenTK.Graphics.GL)to typeof(OpenTK.Graphics.OpenGL.GL).

Edit: This code works correctly.

            Assembly assembly = null;
 
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (a.FullName.Contains("OpenTK"))
                {
                    assembly = a;
                }
            }
 
            Type type = assembly.GetType("OpenTK.Graphics.OpenGL.GL");
            object gl = Activator.CreateInstance(type);
            MethodInfo mi = type.GetMethod("LoadAll", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            mi.Invoke(gl, null);
AdrianPi's picture

Good point!

I'm calling GL.LoadAll directly.

But now I get "No graphics context available in the calling thread".

The rendering context has been created in C++ and made active, before calling this C# code via interop.

How can I get OpenTK to know there is an "alien" context created? :)