lightmap Posted September 26, 2017 Share Posted September 26, 2017 Hello I trying to call c# function from unigine script : here main function that initializes costum worldLogic ( initializes costum hirachy structure from HUGE *.node file ) public static void TestCallFunc() { Log.message("TestCallFunc\n"); } static void Main(string[] args) { Wrapper.init(); Engine engine = Engine.init(Engine.VERSION, args); ControlLogic.SetUnigineApp(App.get()); AppWorldLogic worldLogic = new AppWorldLogic(); Interpreter.addExternFunction("TestCallFunc", new Interpreter.Function0(TestCallFunc)); Log.message("Interpreter.addExternFunction {0}\n",App.get()); engine.main(null, worldLogic, null);// here error occurs Engine.shutdown(); } public class AppWorldLogic : WorldLogic { // World logic, it takes effect only when the world is loaded. // These methods are called right after corresponding world script's (UnigineScript) methods. public AppWorldLogic(){ Log.message("AppWorldLogic constr\n"); } public override int init(){ Log.message("AppWorldLogic.init()\n"); // Write here code to be called on world initialization: initialize resources for your world scene during the world start. DictionaryClass.ReadFromFile("TreeDictionary.txt"); IssTreeVM.FillIssTree(); ControlLogic.init_ui(); return 1; }//-----in debug step-bystep, error message popup after this line .... if I remove "Interpreter.addExternFunction("TestCallFunc"" - or - comment "TestCallFunc();" callback from unigine script - all goes fine ! else it crushes with useless details in search for file "d:\BuildAgent\work\32ae776d4ea36e16\source\csharp\library\UnigineLogic.cs" any notes to solve it? Link to comment
ded Posted September 27, 2017 Share Posted September 27, 2017 Hi Mikhail, I've successfully reproduced this crash. It happens because garbage collector at some point destroys delegate that you pass to the Interpterer. I'll have this fixed. As a workaround, you can use this code: var callback = new Interpreter.Function0(TestCallFunc); GCHandle handle = GCHandle.Alloc(callback); Interpreter.addExternFunction("TestCallFunc", callback); And if you're planning to add a lot of functions, you can write something like this: class DelegatePinner : IDisposable { private List<GCHandle> handles; public DelegatePinner() { handles = new List<GCHandle>(); } public T pin<T>(T func) { if (func != null) handles.Add(GCHandle.Alloc(func)); return func; } public void Dispose() { foreach (var h in handles) h.Free(); } }; ... using (DelegatePinner pinner = new DelegatePinner()) { Interpreter.addExternFunction("func0", pinner.pin(new Interpreter.Function0(func0))); Interpreter.addExternFunction("func1", pinner.pin(new Interpreter.Function0(func1))); Interpreter.addExternFunction("func2", pinner.pin(new Interpreter.Function0(func2))); engine.main(null, worldLogic, null); Engine.shutdown(); } 1 Link to comment
lightmap Posted September 27, 2017 Author Share Posted September 27, 2017 Thank you, ded! DelegatePinner solved issue Link to comment
Recommended Posts