❔ Loading arbitrary values onto a ILGenerator stack
hey! i'm new to c# and i have a question/issue regarding the ILGenerator.
I am trying to use a function from JS to subscribe to an event handler. What I came up with was extracting the correct argument types using Reflection (from the target event's
Invoke
function) and then creating a DynamicMethod
to call the JS function, using ILGenerator.EmitCall
.
After hours of trying to do this, I noticed something: calling the JS function requires 3 arguments (first one being null), but I only have 2.
Is there a way to load a null value to Ldarg_0
without messing with the arguments of the dynamic method? I took a look at the Opcodes
class (not everything obv) and couldn't find any load operations related to that. any suggestions are appreciated because I really don't know what to do now 🙃36 Replies
What exactly are you trying to solve?
This seems very over engineered if you just wanna call a js method
Can you not use IJSRuntime? Or JsImport/JsExport
I'm trying to load JS files and allow them to register for events using a normal syntax, something like
Using Reflection, I can get the event by "walking" the path provided just fine. However, registering the function is the complicated part.
I was following a Microsoft tutorial which involved creating an Assembly at runtime, which I judged an overkill and decided to make it a dynamic method instead. However the fact that the signature of the JS function doesn't match CSharp's is stopping me, because there's an argument missing when I use
EmitCall
.
I could just make the first argument an enum, however that'd require a HUGE switch/case mess because there are a lot of events.
Also, by doing this, I could also allow reloading those functions by storing the callback and removing it using RemoveEventHandler
whenever I need.
I am not familiar with those. Are they from Jint? Currently I'm using normal modules and providing a C# class so the script can interact with the rest of the program using higher level code (a.k.a. no interacting directly with c# built-in classes and functions)Run .NET from JavaScript
Learn how to run .NET from JavaScript.
This Stuff
Can you not use it?
does it work with .net core 5.0?
.net 7 i think
it's very EOL but I'm stuck to it
Hmmm
yeah, can't then
So whats the first arg of ur js function?
the javascript function looks like this
where
sender
is the event sender and args are the actual data.
However, to call it from C#, it's this:
where null
is a JS object (don't need it) and a
b
are JsValue params (C# types get automatically converted to it unless using the ILGen has some weird effect or something)Got it but what's the problem now? Why can you not just keep using null?
this is what the code looks like
and this is what I get
oops accidentally cut the lines but 78 is the CreateDelegate one
the most obvious issue here is the fact that the
Call
method I've got at methodOverload
has 3 arguments, while I've only got 2 loaded on my IL stackCan u not just use https://learn.microsoft.com/en-us/dotnet/api/system.reflection.emit.opcodes.ldnull?view=net-7.0
OpCodes.Ldnull Field (System.Reflection.Emit)
Pushes a null reference (type O) onto the evaluation stack.
If not I'd just create a simple method with 3 params like urs and call the method from another one.
Then go to sharplab and see what the IL code is
the error isnt because you emitted something wrong
you're trying to create a delegate that doesnt have the same signature as the dynamic method
what is the event handler type, and what arguments does your dynamic method take/what does it return
the dynamic method takes types extracted from the event Invoke function, which would be
object
for the sender and ButtonPressedArgs
for the arg
btw the sender is null (not sure if this usual or not)
thats useful! thank u so much, its going to save me from implementing a method just for that
however as @Windows10CE still doesn't work. the stack thing was going to be an issue but not anymore
cant bind to the target method because its signature is not compatible with that of the delegate typecould you send the entire method
as text
you can use $paste if its long
If your code is too long, you can post to https://paste.mod.gg/ and copy the link into chat for others to see your shared code!
https://paste.mod.gg/adjbcyxauzhs/0 i think this is it
BlazeBin - adjbcyxauzhs
A tool for sharing your source code with the world!
oh
i see now
you have a
typeof(JsVelvet)
on the end of your DynamicMethod constructor
pretty sure that shouldnt be there
actually
that seems to not matter
nevermindlemme try taking it out, it's from stuff i was trying out earlier
actually why do you have
_modEntry
on the CreateDelegate
yeah thats what it isit's the target
doesn't work without it too if i recall correctly
lemme try it
adding it to my testing gets me the same exception as you
oh ok, did this before
now it says the object does not match the target type when attaching the event handler. thats because of the _modEntry in the AddEventHandler.
but setting it to null creates another error, saying the target can only be set as null if the method is static iirc
let me try it again
yeah, non-static method requires a target
what complains about that
AddEventHandler or CreateDelegate
the addeventhandler
AddEventHandler needs an instance of
ev.DeclaringType
whatever that happens to belemme try with it
like if i have
for TestEvent, you need an instance of A to pass to AddEventHandler
ohhh ok
i tried ev.DeclaringType literally lol
that worked im cryinggggggg
just some il errors now because of the generator
thank you so muchhh
these have been some interesting 72h of using c# 😭
Note, dynamically generating code by building a System.Linq.Expressions.Expression and then
.Compile()
ing it is a lot easier than doing IL generation. The end result is the same, but it works at a higher levelWas this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.