locked
[Solved] SmallBasic can't find my extension. RRS feed

  • Question

  • Hello,

    I'm in the process of developing a very simple 2D game engine for Small Basic, using OpenTK.
    The core of the library is mostly done, now I've started working on the SmallBasic interfacing.

    However, I've stumbled upon a problem: The SmallBasic editor (and compiler) do not detect my library at all.
    The code conforms to every rule of a SmallBasic extension:

    1. Exposed types should be static and decorated with the [SmallBasicType] attribute
    2. Properties and input/output of methods should be of type Primitive
    3. Events should be of type SmallBasicCallback
    4. The DLL must be placed in the lib folder of the SmallBasic installation directory.

    Even with those 4 facts being fulfilled, SB still can't find my extension.
    I've made sure it's being compiled with .NET 4.5 and is on Release mode.

    You can take a look a the code and get a copy of the DLL at the Git repository.

    Has anyone run into a similar problem before?

    Thanks in advance,

    Leonardo Giovanni Scur


    • Edited by Kroltan Wednesday, July 22, 2015 3:43 PM
    Monday, July 20, 2015 2:46 AM

Answers

  • I tried the following:

    Create a new project to wrap the TK, it is a standard .Net 4.5 C# class with a refernce to SmallBasicLibrary and SmallTK - just add these 2 - you don't need some of the others I have below added while testing.


    Add a using SmallTK and create public static functions to those in SmallTK.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.SmallBasic.Library;
    using SmallTK;
    
    namespace SmallTKWrapper
    {
        /// <summary>
        /// Test Project
        /// </summary>
        [SmallBasicType]
        public static class SmallTK
        {
            /// <summary>
            /// This is called every frame, and is where most of the game happens.
            /// </summary>
            public static event SmallBasicCallback OnUpdate
            {
                add
                {
                    GameEngine.OnUpdate = value;
                }
                remove
                {
                    GameEngine.OnUpdate = null;
                }
            }
    
            /// <summary>
            /// This is called when the engine starts and is ready to go.
            /// </summary>
            public static event SmallBasicCallback OnLoad
            {
                add
                {
                    GameEngine.OnLoad = value;
                }
                remove
                {
                    GameEngine.OnLoad = null;
                }
            }
    
            /// <summary>
            /// This is called after the engine has finished closing.
            /// </summary>
            public static event SmallBasicCallback OnStop
            {
                add
                {
                    GameEngine.OnStop = value;
                }
                remove
                {
                    GameEngine.OnStop = null;
                }
            }
    
            /// <summary>
            /// Starts the engine, trying to run at the given framerate.
            /// </summary>
            /// <param name="fps">The target framerate</param>
            public static void Start(Primitive fps)
            {
                GameEngine.Start(fps);
            }
    
            /// <summary>
            /// Stops the game, and calls OnStop.
            /// </summary>
            public static void Stop()
            {
                GameEngine.Stop();
            }
        }
    }

    I hooked up the events and public methods for GameEngine - the events modified in GameEngine.cs:

            public static SmallBasicCallback OnUpdate = null;
            public static SmallBasicCallback OnLoad = null;
            public static SmallBasicCallback OnStop = null;

    I then copied dlls/xml to lib

    SmallTKWrapper.dll and SmallTKWrapper.XML

    Additionally, at this stage I had to add the following other dlls to the sb source/exe folder (they could be extracted from resources later or handled in some way)

    SmallTK.dll and log4net.dll

    Run SB and they appear - it creates a gamewindow and fires load event and you can proceed to debug from here.

    SmallTK.OnLoad = OnLoad
    SmallTK.Start(50)

    While ("True")
      Program.Delay(100)
    EndWhile

    Sub OnLoad
      TextWindow.WriteLine("OnLoad")
    EndSub

    EDIT

    ILMerge can combine all required dlls once you get it working - just put the extra ones in sb/exe folder for now to get the sprites and everything else going first.

    For reference this is the ILMerge batch file I needed and the dlls.


    cd "C:\Program Files (x86)\Microsoft\Small Basic\lib"
    del *.pdb
    ILMerge /lib:..\ /xmldocs /ndebug /allowDup /targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5" /out:SmallTKWrapper.dll SmallTKWrapper.dll SmallTK.dll log4net.dll ObjectTK.Tools.dll ObjectTK.dll OpenTK.dll OpenTKLearn.dll
    rem del SmallTK.dll log4net.dll ObjectTK.Tools.dll ObjectTK.dll OpenTK.dll OpenTKLearn.dll *.pdb
    pause




    • Edited by litdev Monday, July 20, 2015 10:07 PM
    • Marked as answer by Kroltan Monday, July 20, 2015 10:39 PM
    Monday, July 20, 2015 9:41 PM
  • I rebuilt everything I needed including some of the OpenTK bits I think targeting .Net4.5, some were .Net4.0 using VS 2015 Community - I will bundle my whole directory up as a zip later this evening (it will be after 9pm UK time) and upload somewhere if its not too big.
    • Marked as answer by Kroltan Wednesday, July 22, 2015 2:46 PM
    Tuesday, July 21, 2015 2:34 PM
  • Maybe write a small test sample. Points of care for me were making sure Project properties and references were correct.

    I use Liams article as guide.

    It showed up in the SB1.1 IDE just fine.

    using Microsoft.SmallBasic.Library;
    
    namespace TestExtension
    {
        /// <summary>
        /// Test Extension for Small Basic v1.1
        /// </summary>
    
        [SmallBasicType]
        public static class HelloWorld
        {
            /// <summary>
            /// Returns some text.
            /// </summary>
            /// <param name="text">Text to be returned.</param>
            /// <returns>The text specified.</returns>
    
            public static Primitive Show(Primitive text)
            {
               return (Primitive) text;
            }
        }
    }

    Monday, July 20, 2015 7:52 PM
  • Tuesday, July 21, 2015 8:07 PM

All replies

  • Don't know much about this..

    But you need to recompile the extensions using small basic v1.1

    Also I remember reading somewhere about others having trouble locating them.

    Maybe look through some of litdevs forum threads or check his website.


    • Edited by Jibba j Monday, July 20, 2015 6:47 AM
    Monday, July 20, 2015 6:16 AM
  • Yes, I've taken care to compile the extension with .NET 4.5 (used by SB v1.1)

    I'll take a look at LitDev's forums.

    Monday, July 20, 2015 2:12 PM
  • Well, I've searched around the forums, but there are little to no posts about extension development, much less for SB 1.1.

    I got LitDev's source and looked through it, but the project settings seem to be equivalent.

    What I did notice is that SB is reading and loading the DLL (it becomes locked while the editor is open), but still does not detect the objects for use.

    I'm using Costura.Fody to merge the dependency DLLs into one single DLL, but even using the usual separate DLLs stills results in the same result: no objects from the extension appear.

    I've made sure all the dependencies are compiled for .NET 4.5, by downloading their source and manually compiling them.

    Monday, July 20, 2015 5:06 PM
  • Hello,

    I think the DLL is blocked.

    You must unblock the DLL in the .../lib - directory and start small basic again.

    If the DLL is still blocked , copy the file to a directory with more rights, unblock there and copy backwards.

    For detailed instructions see on Litdevs download page .

    Good luck !

    Monday, July 20, 2015 6:50 PM
  • I thought about that at first, but it is not the case.

    Windows only blocks DLLs that come from the internet, and since I've compiled this one myself, it was not blocked.

    Thanks for helping, though..
    • Edited by Kroltan Monday, July 20, 2015 6:54 PM
    Monday, July 20, 2015 6:54 PM
  • I donloaded and could recompile and reproduce your problem.

    I cannot see any obvious settngs problem .Net4.5 Release AnyCPU [SmallBasicType] public static etc - I even tried adding a simple new c# file with just a very simple test extenson.

    So I conclude that it is probably something to do with Fody and other NuGet bits.  Not sure at all which or why.

    I would start with a simple project that works in SB, then slowly add the nuget packages without using them, then try to reference and use them - at some point it will fail and maybe some ideas will emerge.

    Monday, July 20, 2015 7:30 PM
  • Maybe write a small test sample. Points of care for me were making sure Project properties and references were correct.

    I use Liams article as guide.

    It showed up in the SB1.1 IDE just fine.

    using Microsoft.SmallBasic.Library;
    
    namespace TestExtension
    {
        /// <summary>
        /// Test Extension for Small Basic v1.1
        /// </summary>
    
        [SmallBasicType]
        public static class HelloWorld
        {
            /// <summary>
            /// Returns some text.
            /// </summary>
            /// <param name="text">Text to be returned.</param>
            /// <returns>The text specified.</returns>
    
            public static Primitive Show(Primitive text)
            {
               return (Primitive) text;
            }
        }
    }

    Monday, July 20, 2015 7:52 PM
  • I tried the following:

    Create a new project to wrap the TK, it is a standard .Net 4.5 C# class with a refernce to SmallBasicLibrary and SmallTK - just add these 2 - you don't need some of the others I have below added while testing.


    Add a using SmallTK and create public static functions to those in SmallTK.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Microsoft.SmallBasic.Library;
    using SmallTK;
    
    namespace SmallTKWrapper
    {
        /// <summary>
        /// Test Project
        /// </summary>
        [SmallBasicType]
        public static class SmallTK
        {
            /// <summary>
            /// This is called every frame, and is where most of the game happens.
            /// </summary>
            public static event SmallBasicCallback OnUpdate
            {
                add
                {
                    GameEngine.OnUpdate = value;
                }
                remove
                {
                    GameEngine.OnUpdate = null;
                }
            }
    
            /// <summary>
            /// This is called when the engine starts and is ready to go.
            /// </summary>
            public static event SmallBasicCallback OnLoad
            {
                add
                {
                    GameEngine.OnLoad = value;
                }
                remove
                {
                    GameEngine.OnLoad = null;
                }
            }
    
            /// <summary>
            /// This is called after the engine has finished closing.
            /// </summary>
            public static event SmallBasicCallback OnStop
            {
                add
                {
                    GameEngine.OnStop = value;
                }
                remove
                {
                    GameEngine.OnStop = null;
                }
            }
    
            /// <summary>
            /// Starts the engine, trying to run at the given framerate.
            /// </summary>
            /// <param name="fps">The target framerate</param>
            public static void Start(Primitive fps)
            {
                GameEngine.Start(fps);
            }
    
            /// <summary>
            /// Stops the game, and calls OnStop.
            /// </summary>
            public static void Stop()
            {
                GameEngine.Stop();
            }
        }
    }

    I hooked up the events and public methods for GameEngine - the events modified in GameEngine.cs:

            public static SmallBasicCallback OnUpdate = null;
            public static SmallBasicCallback OnLoad = null;
            public static SmallBasicCallback OnStop = null;

    I then copied dlls/xml to lib

    SmallTKWrapper.dll and SmallTKWrapper.XML

    Additionally, at this stage I had to add the following other dlls to the sb source/exe folder (they could be extracted from resources later or handled in some way)

    SmallTK.dll and log4net.dll

    Run SB and they appear - it creates a gamewindow and fires load event and you can proceed to debug from here.

    SmallTK.OnLoad = OnLoad
    SmallTK.Start(50)

    While ("True")
      Program.Delay(100)
    EndWhile

    Sub OnLoad
      TextWindow.WriteLine("OnLoad")
    EndSub

    EDIT

    ILMerge can combine all required dlls once you get it working - just put the extra ones in sb/exe folder for now to get the sprites and everything else going first.

    For reference this is the ILMerge batch file I needed and the dlls.


    cd "C:\Program Files (x86)\Microsoft\Small Basic\lib"
    del *.pdb
    ILMerge /lib:..\ /xmldocs /ndebug /allowDup /targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5" /out:SmallTKWrapper.dll SmallTKWrapper.dll SmallTK.dll log4net.dll ObjectTK.Tools.dll ObjectTK.dll OpenTK.dll OpenTKLearn.dll
    rem del SmallTK.dll log4net.dll ObjectTK.Tools.dll ObjectTK.dll OpenTK.dll OpenTKLearn.dll *.pdb
    pause




    • Edited by litdev Monday, July 20, 2015 10:07 PM
    • Marked as answer by Kroltan Monday, July 20, 2015 10:39 PM
    Monday, July 20, 2015 9:41 PM
  • That's very well explained!
    So, what you did to get it working was to add another wrapping layer that only dealt with SmallTK? How curious...
    Maybe the SB extension loader only checks dependencies 1 level deep, and doesn't like OpenTK.

    I was going to post this sooner, but I had to leave the computer for a while. It's a step by step inspection on what causes the problem. I'll paste it here for archiving purposes:

    Created a new project, without Costura.Fody

    • Added first the GameEngine class (where all the SB linkings are). That worked, in the sense that SmallBasic detected the extension.
    • Then I added the SmallTkGame class, where the OpenTK side resides, without using the Sprites class. Boom, no more extension.

    Removed SmallTkGame, reset dependencies only to System and SB.

    • Added Sprites class, commenting all the code which depended on OpenTK/ObjectTK, and making all methods return true, so it's a blank API. That gets recognized.

    Then I added back OpenTK, ObjectTK and the OpenTKGame dependencies that I compiled (no nuget, release mode, any cpu), but did not use them. SB recognizes extension.

    • Started uncommenting the code in Sprites, allowing it to depend into OpenTK and OpenTKGame. Compiles fine and SB recognizes.
    • Re-added SmallTkGame class, modifying it to not depend on ObjectTK (strong suspicion). Now SmallBasic cannot detect the extension. ObjectTK doesn't seem to be the fault.
    • Removed uses of OpenTK.Graphics.OpenGL from SmallTkGame. Still no extension.
    • Removed uses of OpenTK from SmallTkGame. SmallBasic recognizes!

    Note that while the OpenTK reference in SmallTkGame seemed to be problematic, it is being used by Sprites with no apparent conflicts. Note that no code has run yet.

    • Added back the code that uses OpenTK.Graphics.OpenGL, works fine.
    • When OpenTKLearn.GameWindow and related code is used, SB can't recognize.

    So I guess the culprit is something within the OpenTK, or how I use it.


    • Marked as answer by Kroltan Monday, July 20, 2015 10:39 PM
    • Unmarked as answer by Kroltan Monday, July 20, 2015 10:39 PM
    • Edited by Kroltan Monday, July 20, 2015 10:40 PM
    Monday, July 20, 2015 10:38 PM
  • Well, I tried your changes, and it sort of works. It does get recognized fully by SB, however when I try to run the sample you exemplified, I get an exception:

    https://msdn.microsoft.com/en-us/library/bb264475%28VS.100%29.aspx?f=255&MSPPError=-2147217396

    System.TypeInitializationException: O inicializador de tipo de 'OpenTK.DisplayDevice' acionou uma exceção.
     ---> System.TypeInitializationException: O inicializador de tipo de 'OpenTK.Platform.Factory' acionou uma exceção.
      ---> System.MethodAccessException: Falha no método transparente de segurança 'OpenTK.Platform.Windows.WinFactory.LoadOpenGL()' ao chamar o código nativo por meio do método 'OpenTK.Platform.Windows.Functions.LoadLibrary(System.String)'. Os métodos devem ser críticos de segurança ou críticos para segurança e disponíveis no código transparente para chamar códigos nativos.
       em OpenTK.Platform.Windows.WinFactory.LoadOpenGL()
       em OpenTK.Platform.Windows.WinFactory..ctor()
       em OpenTK.Platform.Factory..ctor()
       em OpenTK.Toolkit.Init(ToolkitOptions options)
       --- Fim do rastreamento de pilha de exceções internas ---
       em OpenTK.Platform.Factory.get_Default()
       em OpenTK.DisplayDevice..cctor()
       --- Fim do rastreamento de pilha de exceções internas ---
       em OpenTK.DisplayDevice.get_Default()
       em ObjectTK.Tools.DerpWindow..ctor(Int32 width, Int32 height, GraphicsMode mode, String title)
       em OpenTKLearn.GameWindow..ctor()
       em SmallTK.GameEngine.Start(Primitive fps)
       em SmallGame.GameEngine.Start(Primitive fps)

    Basically, from what I could gather, OpenTK is somehow not permitted to invoke certain native code on .NET 4.0+

    I know this is kind of my job, but I'm curious as to how you did not receive such exception?

    Monday, July 20, 2015 11:31 PM
  • I rebuilt everything I needed including some of the OpenTK bits I think targeting .Net4.5, some were .Net4.0 using VS 2015 Community - I will bundle my whole directory up as a zip later this evening (it will be after 9pm UK time) and upload somewhere if its not too big.
    • Marked as answer by Kroltan Wednesday, July 22, 2015 2:46 PM
    Tuesday, July 21, 2015 2:34 PM
  • Oh, don't spend too much time on this, but if it isn't much trouble for you, I'll be grateful.

    I'll double-check my sources for OpenTK.

    Thanks,

    Leonardo G. Scur

    Tuesday, July 21, 2015 3:01 PM
  • Tuesday, July 21, 2015 8:07 PM
  • Thank you for taking your time to help me!
    I recompiled all dependencies and now everything is working.

    Maybe very soon a first release will be published for the SB community to use.

    Wednesday, July 22, 2015 3:42 PM