Apple recently deprecated the MIDIDestinationCreate method and replaced it with a MidiDestinationCreateWithProtocol (MIDIDestinationCreate)
The old method required to pass a simple callback method 'MIDIReadProc' which from C# could be done by creating the following delegate signature, then creating a delegate and assigning a method as the callback. We declare the delegate signature:
internal delegate void MIDIReadProc(MIDIPacketListPtr pktlist, IntPtr readProcRefCon, IntPtr srcConnRefCon);
Create a delegate to assign our callback method to:
private CoreMidiInterop.NativeMethods.MIDIReadProc m_readProcDelegate;
Assign a method to the delegate we created:
m_readProcDelegate = CallMessageReceived;
Create a callback method, that should receive MIDI messages from macOS Core MIDI:
private void CallMessageReceived(MIDIPacketListPtr pktlist, IntPtr readProcRefCon, IntPtr srcConnRefCon)
{
...
}
Eventually pass this delegate to the apple Core MIDI method:
CoreMidiInterop.NativeMethods
.MIDIDestinationCreate(m_clientRef, CoreFoundationUtils.ToCFStringRef(name), m_readProcDelegate, CFStringRef.Zero, out MIDIEndpointRef destinationRef);
This all works as expected.
That's now deprecated and no longer works on macOS Big Sur. The new method "MidiDestinationCreateWithProtocol" requires an apple block to use as the callback param (called MIDIReceiveBlock readBlock):
OSStatus MIDIDestinationCreateWithProtocol(MIDIClientRef client, CFStringRef name, MIDIProtocolID protocol, MIDIEndpointRef *outDest, MIDIReceiveBlock readBlock);
The documentation here: MIDIReceiveBlock
How is it possible to create an apple block with C# code? I've been searching for examples but cannot find any. I did start looking at the underlying implementation of apple blocks here:
Block Implementation Specification
It's no simple thing, so any help/example of how to do this in C# would be really helpful.
First, I feel that Apple is being inconsistent with their use of the word "deprecate". Since these new functions involving the words "WithProtocol" are only valid for Big Sur at this time, I don't see how all previous code can be deprecated until the previous versions of the operating system are no longer supported. See https://bradleyross.github.io/ObjectiveC-Examples/Documentation/BRossTools/FunctionalArea.html.
See https://bradleyross.github.io/ObjectiveC-Examples/Documentation/BRossTools/CoreMidi.html#MIDIDestinationCreateWithBlock MIDIDestinationCreate should indeed be deprecated, but MIDIDestinationCreateWithProtocol is only for BigSur. In addition the "WithProtocol" functions are to support MIDI 2.0, and the full specifications for MIDI 2.0 have not yet been released to the general public. I would therefore prefer to use MIDIDestinationCreateWithBlock. See the Xcode project BRossTools in the GitHub project at https://github.com/BradleyRoss/ObjectiveC-Examples. You can search this repository for the names of the CoreMIDI functions you are looking for and it may help. You might also want to look at https://github.com/mixedinkey-opensource/MIKMIDI. Part of the problem is that the functions ending with "WithBlock" and most of the functions ending with "WithProtocol" use closures (another name for blocks). I'm not sure how C# closures and CLANG closures (used in Objective-C) compare. Try to look for information on C# closures.
Related
Can someone give me an example of the use of the RunCommand method that takes a string argument only (called CommandName) available in the MongoDB .NET driver? I know there is an overloaded RunCommand method that takes an object reference (I think a CommandDocument object) as an argument, but I'd rather not use that one.
I'm having trouble getting the syntax right for CommandName. Thanks in advance!
If you are using some recent version of the official C# driver, the "real" string based version you are referring to (CommandResult RunCommand(string commandName)) is only part of the legacy driver component (check the namespace). I would hence not recommend using it.
The "official" interface currently looks like this:
TResult RunCommand<TResult>(Command<TResult> command, /* and some additional optional parameters */)
And since the C# driver heavily relies on implicit type conversions, there also is one from a string (and a BsonDocument) to the corresponding sub types of Command<TResult> (JsonCommand<TResult> and BsonDocumentCommand<TResult>). So you can effectively pass a string to the above new RunCommand() method, too.
You can therefore write either one of the following lines both of which do the exact same thing:
RunCommand<BsonDocument>("{count: \"collection_name\"}")
RunCommand<BsonDocument>(new BsonDocument("count", "collection_name"))
I'm playing around with the C# reflection API. I can easily load Type information of classes, methods etc. in an assembly, however, now I wonder how can I load and read the code inside a method?
Basic Answer:
You can't with the reflection API (System.Reflection).
The reason is that the reflection api is designed to work on Metadata (Type of Classes, Name and Signature of Methods, ...) but not on the data level (which would be the IL-stream itself).
Extended Answer:
You can emit (but not read) IL with System.Reflection.Emit (e.g. ILGenerator Class).
Through MethodInfo.GetMethodBody() you can get the binary IL-stream for the implementation of a method. But thats usually completely useless by itself.
There are external libraries (like Cecil) that you can use to read/modify/add/delete code inside a method.
That depends on what you mean by "read the code." There are 4 forms of the code.
Code Type
Can get with Reflection
The source code, i.e. the original C# or VB.NET
No
The symbolic IL code
No
The JITed assembly code
No
The IL bytes, i.e. the actual bytes that IL is compiled to
Yes
Take a look at MethodBase.GetMethodBody() for the last one. You can get the IL bytes, the local variables, exception frames etc.
You sort of can. The relevant function is MethodBase.GetMethodBody.
It's not exactly the most useful API. You can get some basic information about what's inside the method, and you can obtain the IL as a byte array. That's about it.
There's a slightly better API in the Mono.Cecil library, which exposes a MethodDefinition class with its own MethodBody implementation which contains actual Instructions, so you don't have to interpret the raw byte code. Still, if you're looking to get C# code out of it à la Reflector, you're going to be sorely disappointed. Also, Cecil isn't very well documented.
If you still want to try, then good luck.
If you don't need to do this real-time, have a look at Reflector. You can disassemble any .NET assembly (including the MS core DLLs) and see the code in your language of choice. This can be very educational.
Update Has anyone tried using Reflector on Reflector to figure out how this is done?
I'd like to provide an example of how one could explore the code inside a method. As others have explained, this can't be done easily using the native .NET Reflection API. However, using the Mono.Reflection API, you can disassemble the code programmatically using the GetInstructions() method and inspect it at runtime.
For example, the following code inspects a method and computes the number of calls inside it. As a use case for such a code, say I am a teacher (which I am) and instruct my fellow students to program a given method without using any other method, then using this code in unit tests I can verify that the given constrain is respected.
public static class MethodInfoUtil
{
public static int NbOfInnerCalls(this MethodInfo mi)
{
return mi.GetInstructions().Count(
instruction => instruction.OpCode.FlowControl == FlowControl.Call);
}
}
Example Console program:
class Program
{
static int Add(int a, int b) => a + b;
static int Doubling(int a) => Add(a, a);
static int Quadrupling(int a) => Add(Add(a, a), Add(a, a));
static void Main(string[] args)
{
Console.WriteLine("Inner method calls");
Console.WriteLine(" Add: {0}", ((Func<int, int, int>)Add).Method.NbOfInnerCalls());
Console.WriteLine(" Doubling: {0}", ((Func<int, int>)Doubling).Method.NbOfInnerCalls());
Console.WriteLine("Quadrupling: {0}", ((Func<int, int>)Quadrupling).Method.NbOfInnerCalls());
}
}
// Output:
// Inner method calls
// Add: 0
// Doubling: 1
// Quadrupling: 3
No
This is a feature slated for the next version of C#. You can use the CodeDom to get more info than reflection, but you cannot interrogate the parse tree yet.
Well there is always mono, in mono the compiler is a service, and you could get the parse trees at runtime.
The better question is why you want to?
Yes, there must be a way to achieve this: The .NET Reflector tool does this, too. Can't tell you how it's done there, though.
I'm playing around with the C# reflection API. I can easily load Type information of classes, methods etc. in an assembly, however, now I wonder how can I load and read the code inside a method?
Basic Answer:
You can't with the reflection API (System.Reflection).
The reason is that the reflection api is designed to work on Metadata (Type of Classes, Name and Signature of Methods, ...) but not on the data level (which would be the IL-stream itself).
Extended Answer:
You can emit (but not read) IL with System.Reflection.Emit (e.g. ILGenerator Class).
Through MethodInfo.GetMethodBody() you can get the binary IL-stream for the implementation of a method. But thats usually completely useless by itself.
There are external libraries (like Cecil) that you can use to read/modify/add/delete code inside a method.
That depends on what you mean by "read the code." There are 4 forms of the code.
Code Type
Can get with Reflection
The source code, i.e. the original C# or VB.NET
No
The symbolic IL code
No
The JITed assembly code
No
The IL bytes, i.e. the actual bytes that IL is compiled to
Yes
Take a look at MethodBase.GetMethodBody() for the last one. You can get the IL bytes, the local variables, exception frames etc.
You sort of can. The relevant function is MethodBase.GetMethodBody.
It's not exactly the most useful API. You can get some basic information about what's inside the method, and you can obtain the IL as a byte array. That's about it.
There's a slightly better API in the Mono.Cecil library, which exposes a MethodDefinition class with its own MethodBody implementation which contains actual Instructions, so you don't have to interpret the raw byte code. Still, if you're looking to get C# code out of it à la Reflector, you're going to be sorely disappointed. Also, Cecil isn't very well documented.
If you still want to try, then good luck.
If you don't need to do this real-time, have a look at Reflector. You can disassemble any .NET assembly (including the MS core DLLs) and see the code in your language of choice. This can be very educational.
Update Has anyone tried using Reflector on Reflector to figure out how this is done?
I'd like to provide an example of how one could explore the code inside a method. As others have explained, this can't be done easily using the native .NET Reflection API. However, using the Mono.Reflection API, you can disassemble the code programmatically using the GetInstructions() method and inspect it at runtime.
For example, the following code inspects a method and computes the number of calls inside it. As a use case for such a code, say I am a teacher (which I am) and instruct my fellow students to program a given method without using any other method, then using this code in unit tests I can verify that the given constrain is respected.
public static class MethodInfoUtil
{
public static int NbOfInnerCalls(this MethodInfo mi)
{
return mi.GetInstructions().Count(
instruction => instruction.OpCode.FlowControl == FlowControl.Call);
}
}
Example Console program:
class Program
{
static int Add(int a, int b) => a + b;
static int Doubling(int a) => Add(a, a);
static int Quadrupling(int a) => Add(Add(a, a), Add(a, a));
static void Main(string[] args)
{
Console.WriteLine("Inner method calls");
Console.WriteLine(" Add: {0}", ((Func<int, int, int>)Add).Method.NbOfInnerCalls());
Console.WriteLine(" Doubling: {0}", ((Func<int, int>)Doubling).Method.NbOfInnerCalls());
Console.WriteLine("Quadrupling: {0}", ((Func<int, int>)Quadrupling).Method.NbOfInnerCalls());
}
}
// Output:
// Inner method calls
// Add: 0
// Doubling: 1
// Quadrupling: 3
No
This is a feature slated for the next version of C#. You can use the CodeDom to get more info than reflection, but you cannot interrogate the parse tree yet.
Well there is always mono, in mono the compiler is a service, and you could get the parse trees at runtime.
The better question is why you want to?
Yes, there must be a way to achieve this: The .NET Reflector tool does this, too. Can't tell you how it's done there, though.
The Background (Or, look how far I've gone on my own!)
I'm starting from the Windows 8 Media Extension Sample. I'm using the grayscale example as a starting point to learn how to pass values from managed code into a COM object, and how to pass values from my COM object back to managed code. In my IDL file, I've got a GrayscaleEffect class (taken exactly from the example) and a custom interface that should let me query a string over in the c# world.
The IDL file:
namespace GrayscaleTransform
{
[version(NTDDI_WIN8), uuid(553B5684-4C22-4D21-8638-1E7D86D84F10)]
interface MyInterface : IInspectable {
HRESULT GetMsg([out] HSTRING *message);
}
[version(NTDDI_WIN8)]
runtimeclass GrayscaleEffect {
interface Windows.Media.IMediaExtension;
interface MyInterface;
}
}
My GrayscaleEffect class implementation implements GetMsg to return the string "Woozle"
The relevant c#:
cap = new MediaCapture();
await cap.InitializeAsync();
previewElement1.Source = cap;
await cap.StartPreviewAsync();
PropertySet props = new PropertySet();
await cap.AddEffectAsync(
Windows.Media.Capture.MediaStreamType.VideoPreview,
"GrayscaleTransform.GrayscaleEffect",
props);
if (this.props.ContainsKey("ref"))
{
var augGui = (GrayscaleTransform.MyInterface)this.props["ref"];
string message;
augGui.GetMsg(out message);
}
After the call to GetMsg, I can see that message contains the string "Woozle" just like I expect - Excellent!
The Problem
Now I want to do something a little bit fancier. Instead of a method that lets me pass a string from COM to C#, I want to implement a method that lets me pass a delegate from C# to COM. I'd like to get the MFT class to call this method every 10th video frame or something - that part's not important. I want my interface to have a method called SubscribeEvent that takes a delegate as a parameter. For now, it can be a void delegate that takes no arguments.
This page leads me to believe that I should be able to declare a WinRT delegate over in the COM world and be able to pass a delegate of the same type from C# (see the 3rd item from the end). Cool - seems easy. My best try so far has been something like this in the idl:
delegate void CallbackMethod();
[version(NTDDI_WIN8), uuid(553B5684-4C22-4D21-8638-1E7D86D84F10)]
interface MyInterface : IInspectable {
HRESULT Subscribe(CallbackMethod cb);
}
Unfortunately this results in an error - seems to be related to the declaration of the delegate CallbackMethod:
error MIDL9008: internal compiler problem - See documentation for suggestions on how to find a workaround.
Edit
This one is obvious. That syntax is a C++/cx thing. Upon closer inspection, I don't have the C++/CX extensions turned on. This is a WRL project which means it's regular flavor c++ with template magic.
I also tried to wire up an event by implementing the IConnectionPoint interface, but when I include OCIdl.h I get a compile error that desktop components cannot be compiled for ARM.
The Question
Am I barking up the wrong tree here? Should I be making my GrayscaleEffect class be a WinRT runtime class using C++/CX? Maybe we're venturing into "New question" territory here, but when I try to implement IMFTransform with a WinRT class in C++/CX, I get
error C2811: 'GrayscaleRT::Class1' : cannot inherit from 'IMFTransform', a ref class can only inherit from a ref class or interface class
A better question:
How about this: Can I pass a delegate here at all? I fell like I ought to be able to, if only I knew the magic combination of WRL templates to make it work.
It looks like this is the answer. In WRL, you declare an event in your idl like this:
[uuid(3FBED04F-EFA7-4D92-B04D-59BD8B1B055E), version(NTDDI_WIN8)]
delegate HRESULT WhateverEvent();
See the To add an event that fires when a prime number is calculated section
My problem was that I initially didn't understand that I wasn't using c++/cx. I was using regular c++ with WRL which is a template library similar to ATL that makes WinRT programming easier and doesn't use non-standard language extensions.
Once I understood that, it was relatively easy to find an example of an event handler using WRL
I have discovered the cause of the issue. An answer has been posted below.
EDIT: The problem has changed, please see "The problem" section.
I am using LuaInterface. The generic call for lua functions using this library has this signature LuaFunction.Call(params object[] args). I have created a wrapper function that catches exceptions from the library and formats them for display on the in-game console window.
I am trying to call a lua function, but it is not receiving the arguments. This is the line in C#
Game.Instance.scriptEngine.Call("GenerateChunk", chunks[chunkID], GetChunkGridPosition(chunkID));
Which is simply wrapping a call to this Lua function that accepts two arguments:
//lua
function GenerateChunk(worldChunk, chunkGridPosition)
Log(LogLevel.Error, worldChunk.ToString());
Log(LogLevel.Error, chunkGridPosition.ToString());
end
that merely calls back into a C# Log function (which resolves correctly, and is visible in the Lua context).
The problem is that I am getting an "invalid arguments to method call" error from luainterface when attempting to call the GenerateChunk function, throwing this back:
invalid arguments to method call
at JASG.ScriptEngine.LuaError(Exception ex) Scripting\ScriptEngine.cs:line 144
at JASG.ScriptEngine.Call(String fnName, Object[] args) Scripting\ScriptEngine.cs:line 86
at JASG.ChunkManager.WakeChunk(Int32 chunkID) World\ChunkManager.cs:line 123
at JASG.ChunkManager.GetChunk(Int32 chunkID, Boolean wakeIfAsleep) World\ChunkManager.cs:line 53
I have tried various ways of calling the ScriptEngine.Call method, tried wrapping the arguments in an object[] array, etc., but no dice. Any ideas why lua is not receiving my arguments that I am passing? I have verified both arguments are non-null in C# when being passed in.
I've never used Lua before, but I've seen this kind of strange behaviors with calling COM objects (or any interop), or when the target assembly call is loaded on a different App Domain, or any other technology that intercommunicates a .Net assembly with a non-.Net one.
Have you tried using the [Serializable] attribute on the classes that define the result of "chunks[chunkID]" and "GetChunkGridPosition(chunkID)"? Are all your interop classes and types compatible between both assemblies?
Just thinking out loud here.
Side note: you should reduce your code to the shortest example that produces the problem. For instance, we don't need to see your wrapper function. You should have tried removing it. If that solved the problem, it's an important clue you should have been mentioned. If the problem remained, then that code is just a distracting irrelevancy for anyone reading this.
Your problem could be in your Log function. Everything thing else looks fine, that's the only code we can't actually see, and your problem can be reproduced like this:
public static void Log(int errorLevel, string message)
{
Console.WriteLine(message);
}
public void Test()
{
var lua = new Lua();
lua.RegisterFunction("Log", this, GetType().GetMethod("Log"));
lua.DoString("function foo() Log('a','b') end");
lua.GetFunction("foo").Call();
}
In this case, because 'a' cannot be marshaled into a number.
I incorrectly identified the problem as being with the call into Lua. The error message I was receiving was in fact originating from the Lua script calling back into my C# Log function.
I have discovered the hard way that in spite of exposing the enum LogManager.LogLevel to the lua script envronment, Lua does not support enum types. Thus,
Log(LogLevel.Debug, "hello");
was becoming
Log("Debug", "hello");
when marshalled by LuaInterface for the C# function. It was not until I created an ancillary ScriptLog(string level, string msg) that I was able to properly use the function from within lua. I wanted to keep the functionality of being able to use the enum names within Lua.
NOTE: As Lua does not support enum types, tonumber(LogLevel.Debug) fails as well.