Jump to content

Reflection help to interface with FARAPI


Recommended Posts

Help! I'm trying to interface with the FARAPI via reflection. I'm new to C#, but I found several examples that seemed to work in other mods. The code snip below finds FARAPI, gets the method, then crashes out on creating the delegate. It looks like the method arguments are wrong. I've been struggling with it, maybe someone here can give me a few pointers. I'm probably missing something obvious.

FARAPI definition in FARAPI.cs

public static void CalculateVesselAeroForces(Vessel vessel, out Vector3 aeroForce, out Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude)

The exception:

ArgumentException: method arguments are incompatible

at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, Boolean throwOnBindFailure) [0x00000] in <filename unknown>:0

at System.Delegate.CreateDelegate (System.Type type, System.Reflection.MethodInfo method, Boolean throwOnBindFailure) [0x00000] in <filename unknown>:0

at System.Delegate.CreateDelegate (System.Type type, System.Reflection.MethodInfo method) [0x00000] in <filename unknown>:0

Code snip:

    
// FARAPI Hookups
private delegate void CalculateVesselAeroForcesDelegate(Vessel vessel, Vector3 aeroForce, Vector3 aeroTorque, Vector3 velocityWorldVector, double altitude);

private CalculateVesselAeroForcesDelegate _CalculateVesselAeroForcesDelegate;

private void initFARModel()
{
bool farInstalled = false;
Debug.Log("Trying to detect FARAPI.");
var farapi = AssemblyLoader.loadedAssemblies.SelectMany(x => x.assembly.GetExportedTypes())
.FirstOrDefault(x => x.FullName == "FerramAerospaceResearch.FARAPI");
if (farapi != null)
{
Debug.Log("Found FARAPI. Attempting Reflection...");
var method = farapi.GetMethod("CalculateVesselAeroForces");

if (method != null)
{
Debug.Log("FARAPI method valid. Creating delegate...");
_CalculateVesselAeroForcesDelegate = (CalculateVesselAeroForcesDelegate)Delegate.CreateDelegate(typeof(CalculateVesselAeroForcesDelegate), method);
}

if (_CalculateVesselAeroForcesDelegate != null)
{
farInstalled = true;
Debug.Log("Loaded FARAPI");
}
else
{
Debug.Log("FARAPI found but could not delegate API.");
}

}
}

Link to comment
Share on other sites

I'd try something like this:

            AssemblyLoader.LoadedAssembly FAR = AssemblyLoader.loadedAssemblies.SingleOrDefault(a => a.dllName == "FerramAerospaceResearch");
if (FAR != null)
{
MethodInfo method = null;
try
{
method = FAR.assembly.GetTypes().SingleOrDefault(t => t.Name == "FARAPI").GetMethod("CalculateVesselAeroForces");
}
catch (Exception e)
{
UnityEngine.Debug.LogError("Error finding the method definition\n" + e.StackTrace);
}

try
{
Vector3 force = new Vector3(), torque = new Vector3();
method.Invoke(null, new object[] { FlightGlobals.ActiveVessel, force, torque, Vector3.up, 0d });
}
catch (Exception e)
{
UnityEngine.Debug.LogError("Error invoking method\n" + e.StackTrace);
}
}

I'd start with this. I remember having myself problems when I dealt with reflection and delegates, and somehow delegates just never really worked, and I ended up sticking with just infoking the MethodInfo. So yeah I suggest taking it down bit by bit this way to find what exactly is going wrong.

Link to comment
Share on other sites

Your MethodInfo needs to be created with the all of the arguments that the original method uses.

This:


var method = farapi.GetMethod("CalculateVesselAeroForces", new Type[] { typeof(Vessel), typeof(Vector3), typeof(Vector3), typeof(Vector3), typeof(double) });

instead of this:


var method = farapi.GetMethod("CalculateVesselAeroForces");

I suspect that something special is needed for the first two, out Vector3's.

Link to comment
Share on other sites

I'd try something like this:

  snipped code 

I'd start with this. I remember having myself problems when I dealt with reflection and delegates, and somehow delegates just never really worked, and I ended up sticking with just infoking the MethodInfo. So yeah I suggest taking it down bit by bit this way to find what exactly is going wrong.

@stupid_chris, Thanks! I had tried an invoke earlier and messed that up somehow and fell back to delegates. I read somewhere that delegates are faster but that may not matter here. This looks cleaner so I'll give it a try. In the meantime though DMagic gave me a clue on what else I was doing wrong.

Your MethodInfo needs to be created with the all of the arguments that the original method uses.

This:


var method = farapi.GetMethod("CalculateVesselAeroForces", new Type[] { typeof(Vessel), typeof(Vector3), typeof(Vector3), typeof(Vector3), typeof(double) });

instead of this:


var method = farapi.GetMethod("CalculateVesselAeroForces");

I suspect that something special is needed for the first two, out Vector3's.

@DMagic, Since the method isn't overloaded it appears the method gets reflected correctly without the type. One your second point, your suspicions are correct - the out is significant on the force and torque and it needs to be specified. Also, when I put the out on the arguments, I found out that you have to pass a Vector3 instead of a Vector3d. After some more googling I found I also needed to specify some Bindingflags which seemed to help.

So now I have two working reflection options. It compiles and, well, there is something else wrong. But not this. Thanks! After I clean the code up I'll post something for future reference.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...