What is an "Assembly qualified delegate type name"?
brianjenkins94 opened this issue · 11 comments
Does this provide me a way to specify the function signature of the C# method?
What would an example of this parameter look like?
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
- ID: 83da7030-b5f1-72ad-71f6-424ff45b8b7f
- Version Independent ID: a98926cc-64ab-2911-e4b8-1eaf4573dfe4
- Content: Write a custom .NET Core runtime host - .NET Core
- Content Source: docs/core/tutorials/netcore-hosting.md
- Product: dotnet-core
- GitHub Login: @mjrousos
- Microsoft Alias: tdykstra
Where would I find the implementation that corresponds with this header?:
Ah, it looks like I need to fallback on the CoreClrHost API:
https://github.com/dotnet/runtime/blob/master/src/coreclr/src/hosts/inc/coreclrhost.h#L79-L99
Still interested in the answer to the original question, though.
I'll ping the author on email.
Regarding the original question, yes, my understanding is that HostFxr allows specifying a particular overload of a managed method by giving the (assembly-qualified) name of a delegate defining the method signature (as opposed to hosting with CoreClrHost.h, which only looks up managed entry points by method name).
You should be able to just provide a string containing the assembly-qualified name of the delegate type matching your entry point's signature (including, perhaps, marshaling attributes).
cc'ing @vitek-karas to confirm this, though, because I'm not very experienced with HostFxr.
The code which consumes that string is here: https://github.com/dotnet/runtime/blob/eb95163a0880cac1ba127b81e3cb753e5a65f8cc/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs#L64
If you specify null
it defaults to the `ComponentEntryPoint delegate: https://github.com/dotnet/runtime/blob/eb95163a0880cac1ba127b81e3cb753e5a65f8cc/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs#L19
If you specify a value, it is effectively passed to Type.GetType(yourValue, ...)
: https://github.com/dotnet/runtime/blob/eb95163a0880cac1ba127b81e3cb753e5a65f8cc/src/coreclr/src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComponentActivator.cs#L114
It should be assembly qualified to avoid possible issues with duplicate type names across assemblies, but in reality it's not enforced.
As @mjrousos noted this lets you declare the method signature via declaring a delegate type in C#. The added benefit is that you can use marshalling attributes in the delegate if necessary.
So I should be able to invoke this:
namespace SamplePrecompiledAssembly {
public static class Startup {
public static Func<object, Task<object>> Func(string code) { // <--
Like this?:
returnCode = load_assembly_and_get_function_pointer_fn(loadAssemblyAndGetFunctionPointer)(
assemblyPath.c_str(),
assemblyQualifiedTypeName.c_str(),
methodName.c_str(),
std::string("SamplePrecompiledAssembly.Startup+Func, SamplePrecompiledAssembly").c_str(), // <--
nullptr,
reinterpret_cast<void **>(&run));
The string should point to a delegate type, not a method. So something like this should work:
namespace SamplePrecompiledAssembly {
public static class Startup {
public delegate Func<object, Task<object>> MyFuncDelegate(string);
public static Func<object, Task<object>> Func(string code) {
}
}
}
And then you should be able to use:
SamplePrecompiledAssembly.Startup.MyFuncDelegate
as the string for the function.
Note that given this sample it may not work as I don't know how the interop would marshal a Func<,>
to native code. And even if it did manage to do that, there would be no way from the native code to operate on Task<object>
.
Hmm, I'm beginning to think this might be a product bug.
Steps to Reproduce:
git clone https://github.com/brianjenkins94/Run-DNC.git
cd Run-DNC
npm install
npm build # For whatever reason on Windows you just need to keep building through errors about architecture mismatches and errors writing to the program database.
npm start
Output on Windows 10:
> run-dnc@1.0.0 start C:\Users\User\Documents\GitHub\Run-DNC
> node test.js
get_hostfxr_path() = 0
hostfxr_initialize_for_runtime_config_fn() = 0
hostfxr_get_runtime_delegate_fn() = 0
hostfxr_close_fn() = 0
assembly_path = "C:\\Users\\User\\Documents\\GitHub\\Run-DNC\\src\\SamplePrecompiledAssembly\\bin\\Debug\\netstandard2.1\\SamplePrecompiledAssembly.dll"
type_name = SamplePrecompiledAssembly.Startup, SamplePrecompiledAssembly
method_name = Invoke
delegate_type_name = SamplePrecompiledAssembly.Startup.InvokeDelegate, SamplePrecompiledAssembly
load_assembly_and_get_function_pointer_fn() = 0
run() = 0
Output on macOS 10.15 and Ubuntu 18.04:
> run-dnc@1.0.0 start /Users/bjenks/Sites/Run-DNC
> node test.js
get_hostfxr_path() = 0
hostfxr_initialize_for_runtime_config_fn() = 0
hostfxr_get_runtime_delegate_fn() = 0
hostfxr_close_fn() = 0
assembly_path = "/Users/bjenks/Sites/Run-DNC/src/SamplePrecompiledAssembly/bin/Debug/netstandard2.1/SamplePrecompiledAssembly.dll"
type_name = SamplePrecompiledAssembly.Startup, SamplePrecompiledAssembly
method_name = Invoke
delegate_type_name = SamplePrecompiledAssembly.Startup.InvokeDelegate, SamplePrecompiledAssembly
load_assembly_and_get_function_pointer_fn() = -2146233054
run() = zsh: segmentation fault
So it's working on Windows, but not on Mac or Linux.
Where would be the appropriate place to pursue this? Since I assume docs
isn't it.
I didn't try to run it, but looking at the code there's a difference between Windows and Linux/Mac - when you're calling the load_assembly_and_get_function_pointer
you pass the delegate type name in the Linux/Mac path, but not in the Windows path. Also the output above doesn't seem to match the code in the repo: The code in the repo would specify SamplePrecompiledAssembly.InvokeDelegate
as the delegate type name (without the Startup
) but the output above has it - so maybe you have local fixes?
The error code is COR_E_TYPELOAD
- this would happen if the call Type.GetType(delegateTypeName)
failed.
I made those fixes and it works now.
Thank you very much for your help and patience.