VST Host interop callback exception

Topics: Host Development, Newbie
Apr 9 at 3:48 PM
Hi, I've been looking to build a simple VST host using VST.NET, along the way I've found some issues with loading plugins so decided to do a bit of reverse engineering as a learning exercise to hopefully give me a better understanding of how this is working, creating my own new project to just simply replicate the logic that is used in loading an unmanaged plugin.

I've got to the point where I can call the plugin's main method, passing in a callback method which is successfully getting called. I'll preface this next bit by saying that interop services is not really something I've ever had to look at in much great detail so I'm still bringing myself up to speed.

Within my callback I'm attempting to get the plugin context, though not very successfully. I've managed to narrow it down to this particular bit of code:

System::Runtime::InteropServices::GCHandle gcHandle = System::Runtime::InteropServices::GCHandle::FromIntPtr(intPtr);

Where intPtr is obtained from AEffect's resvd1 property. This always results in the exception:

FatalExecutionEngineError : The runtime has encountered a fatal error. The address of the error was at 0x7374fea5, on thread 0x17f8. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

What I don't understand though, is why this is throwing up errors for me, yet not when the VstUnmanagedPluginContext class is making the same call in the DispatchCallback method with what should be the same data.
Apr 9 at 4:04 PM
Edited Apr 9 at 4:05 PM
I've just started wondering if it's possible that this may possibly be caused by some marshaling error for my AEffect struct resulting in an incorrect pointer being populated into resvd1, here's my AEffect struct (note it's in C#, I find it far less messy to work in than C++):
public unsafe struct AEffect
{
    public int magic;

    public AEffectDispatchCallback dispatcher;

    public AEffectProcessProc process;

    public AEffectSetParameterProc setParameter;

    public AEffectGetParameterProc getParameter;

    public int numPrograms;
    public int numParams;
    public int numInputs;
    public int numOutputs;

    public int flags;

    public IntPtr resvd1;
    public IntPtr resvd2;

    public int initialDelay;

    public int realQualities;
    public int offQualities;
    public float ioRatio;

    public IntPtr @object;
    public IntPtr user;

    public int uniqueID;
    public int version;

    public AEffectProcessProc processReplacing;

    public AEffectProcessDoubleProc processDoubleReplacing;

    public char* future;
}
With an example of its populated data at runtime:

magic = 0

numPrograms = 0
numParams = 20509560
numInputs = 20509904
numOutputs = 269646907

flags = -1

resvd1 = 0x735aedc5
resvd2 = 0x05b20656

initialDelay = 20509868

realQualities = 22550272
offQualities = 0
ioRatio = 1.67413139E-35

object = 0x017c4e38
user = 0x1005ada0

uniqueID = 4
version = 512

Several of the numbers here look off, such as initialDelay, realQualities and the inputs, outputs & params, though with me being new to VSTs (and DSP in general) and not being able to actually set up a proper debug session to allow me to step through the C++ code in the original solution, I don't really have much to compare this data against.

Kind regards
James
Coordinator
Apr 21 at 1:02 PM
First I am very sorry I did not see your message sooner. It seems codeplex does not send notification emails anymore.

It looks like your looking at/using the wrong memory.

VST.NET Host uses the resvd1 field to store a packed reference to the managed plugin context object.
I cannot quit follow what you did or where you're trying to go with this. If you had problems loading plugins, perhaps we should discuss those?
Apr 28 at 12:39 AM
Edited Apr 28 at 12:41 AM
Hi Obi, that's alright, I'm suffering from the same problem, I only just saw that you'd replied.

Ok, yeah you're probably right, lets forget about the above issues that I was having in my little attempt to understand how things are all working. I can't find the code that I'd previously written to attempt to host a plugin using Vst.net so I just wrote a very quick console app to try and replicate the problems I was having before:
using Jacobi.Vst.Interop.Host;
using System;

namespace VstNetTest
{
    class Program
    {
        static void Main(string[] args)
        {
            VstPluginContext context = OpenPlugin(@"C:\Users\james\Downloads\10Band_EQ\10 Band Graphic Eq v1.3.dll");
        }
        
        private static VstPluginContext OpenPlugin(string pluginPath)
        {
            try
            {
                HostCommandStub hostCmdStub = new HostCommandStub();
                hostCmdStub.PluginCalled += new EventHandler<PluginCalledEventArgs>(HostCmdStub_PluginCalled);

                VstPluginContext ctx = VstPluginContext.Create(pluginPath, hostCmdStub);

                // add custom data to the context
                ctx.Set("PluginPath", pluginPath);
                ctx.Set("HostCmdStub", hostCmdStub);

                // actually open the plugin itself
                ctx.PluginCommandStub.Open();

                return ctx;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            return null;
        }
        
        private static void HostCmdStub_PluginCalled(object sender, PluginCalledEventArgs e)
        {
            HostCommandStub hostCmdStub = (HostCommandStub)sender;

            // can be null when called from inside the plugin main entry point.
            if (hostCmdStub.PluginContext.PluginInfo != null)
                Console.WriteLine("Plugin " + hostCmdStub.PluginContext.PluginInfo.PluginID + " called:" + e.Message);

            else
                Console.WriteLine("The loading Plugin called:" + e.Message);
        }
    }
}
This is really just me hacking a few of the bare essentials out of the sample host application, including a copy of the HostCommandStub class from the host sample.

With this I've tried loading in a few plugins, all of which throw an exception that the plugin failed to load, stemming from the VstUnmanagedPluginContext class when I try to actually create the plugin.

It's very possible that I'm doing something wrong, though, with the C#/C++ language split it's been very hard for me to debug and actually see what was causing the problems.

Kind regards
James
Coordinator
Wed at 2:07 PM
So what is the error? Post it so I can have look.