SharpGenTools
SharpGenTools copied to clipboard
Minimal examples fail to generate or crash with NullReferenceException
I'm trying to get started with SharpGen. But I think I'm either missing an important configuration aspect or installed component. Because I can't even get the most minimal case to work. Let me show, two examples.
In all cases the csproj file looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<SharpGenMapping Include="Mappings.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SharpGen.Runtime" Version="1.2.1" />
<PackageReference Include="SharpGenTools.Sdk" Version="1.2.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Example 1, mapping a single function
I've got the following header file encoder.h
void Fourteen();
And the following Mappings.xml
file
<?xml version="1.0" encoding="utf-8"?>
<config id="SuperCompressedNative" xmlns="urn:SharpGen.Config">
<assembly>SuperCompressed</assembly>
<namespace>SuperCompressed.Native</namespace>
<depends>SharpGen.Runtime</depends>
<include-dir override="true">$(THIS_CONFIG_PATH)/../SuperCompressed.Native</include-dir>
<include file="Encoder.h" namespace="SuperCompressed.Native">
<attach>Fourteen</attach>
</include>
<extension>
<create class="Encoders" visibility="public static" />
</extension>
<mapping>
<map function="Fourteen" group="SuperCompressed.Native.Encoders" />
</mapping>
</config>
This fails with the following error:
Severity Code Description Project File Line Suppression State
Error MSB4018 The "GenerateCSharp" task failed unexpectedly.
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxToken.Identifier(GreenNode leading, String text, GreenNode trailing)
at Microsoft.CodeAnalysis.CSharp.SyntaxFactory.Identifier(String text)
at SharpGen.Generator.FunctionCodeGenerator.<GenerateCode>d__4.MoveNext()
at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
at Microsoft.CodeAnalysis.SyntaxList`1.InsertRange(Int32 index, IEnumerable`1 nodes)
at SharpGen.Generator.GroupCodeGenerator.<GenerateCode>d__4.MoveNext()
at System.Linq.Enumerable.<SelectManyIterator>d__17`2.MoveNext()
at Microsoft.CodeAnalysis.CSharp.SyntaxFactory.List[TNode](IEnumerable`1 nodes)
at SharpGen.Generator.RoslynGenerator.GenerateCompilationUnit[T](String csNamespace, IEnumerable`1 elements, IMultiCodeGenerator`2 generator)
at SharpGen.Generator.RoslynGenerator.Run(CsSolution solution, String rootDirectory, String generatedCodeFolder, Boolean includeAssemblyNameFolder)
at SharpGenTools.Sdk.Tasks.GenerateCSharp.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() SuperCompressed C:\Users\Roy\.nuget\packages\sharpgentools.sdk\1.2.1\build\SharpGenTools.Sdk.targets 259
If I remove the <mapping>
part I get the following error, so it looks like it is at least correctly reading the header file:
SG0012 CppFunction [void Fourteen()] is not tagged and attached to any Class/FunctionGroup
Example 2, just auto attach a class
So I thought to myself, ok, maybe I misunderstand mappings, let's try to just auto-attach a simple class. So I changed my header file to:
class Encoder
{
public:
void Ten();
};
And my mappings file to:
<?xml version="1.0" encoding="utf-8"?>
<config id="SuperCompressedNative" xmlns="urn:SharpGen.Config">
<assembly>SuperCompressed</assembly>
<namespace>SuperCompressed.Native</namespace>
<depends>SharpGen.Runtime</depends>
<include-dir override="true">$(THIS_CONFIG_PATH)/../SuperCompressed.Native</include-dir>
<include file="Encoder.h" namespace="SuperCompressed.Native" attach="true"/>
</config>
This does not crash, but only generates the following empty struct:
namespace SuperCompressed.Native
{
// snipped auto-generated documentation
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
public partial struct Encoder
{
}
}
The cause?
Maybe I'm doing something completely wrong? I've been looking at how SharpGen is used in Vortice, and it looks similar. I've also been following the guide at https://sharpgentools.readthedocs.io/en/latest/index.html, but that is a few years old (2018), so maybe its out of date?
I'm running an up-to-date Visual Studio 2022 on Windows 10 (19044.1766) and I've go the .Net Desktop and Desktop Development with C++ workloads installed, together with Windows SDK (10.0.19041.0)
Side note
When I started out with SharpGen I tried to map a class with a std::string
in it, that caused an error that Clang was too old CX0002 #error STL1000: Unexpected compiler version, expected Clang 13.0.0 or newer.
However clang in C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin\clang.exe
is version 13.0.1
. I never was able to resolve that error and then moved to testing more simple cases. But maybe that's a hint something else is wrong?
I assume you saw #101? That appears to be the same issue, and the fix mentioned there worked for me.
Hey, thanks for replying to such an old issue. During that investigation I did not see #101 and I was just about to look into SharpGenTools again to see if it would now be usable for my use case. What a cool coincidence!
Haha no worries, I've been trying to use it for the first time recently, with mediocre results so far. I also encountered this same problem and found both issues, thought I'd link them in case anyone else stumbles into the same problem in the future.
Honestly I'm not impressed by SharpGenTools, but I did eventually get it working on a basic level. I'm probably just going to use it one time to get 80% of the way there, then copy out the generated code and hand-edit it from there.
I got it to compile something useful now, but it does give me an EntryPointNotFoundException when running it. This is probably me doing something wrong in the C++ dll:
Header:
#pragma once
extern "C"
{
__declspec(dllexport) int Fourteen();
}
class file:
#include "NativeFunctions.h"
#include "pch.h"
int Fourteen()
{
return 14;
}
But its not immediately obvious to me what's going wrong.
I think you may need to tack on extern "C"
to the implementation as well to prevent name mangling, i.e.:
#include "NativeFunctions.h"
#include "pch.h"
extern "C" int Fourteen()
{
return 14;
}
But I may be wrong, far from a C/C++ expert.
I got it now, the code was basically correct but I needed to do some tinkering with the settings of the C++ project.
To make sure this is repeatable, and that I don't forget how to do this, I've created a tiny working example and published it in this repository: https://github.com/roy-t/SharpGenToolsExample.
By the way, I think that there is a beta release that has a lot more features. I see that Vortice for example uses version 2.0.0-beta.13. And from my experience Vortice works great: https://github.com/amerkoleci/Vortice.Windows/blob/main/Directory.Packages.props
Maybe that generates better code for you?
@roy-t You can use my branch. I fixed a lot of bugs and added some new features. https://github.com/MikhailGorobets/Diligent-SharpGenTools Here is an example https://github.com/DiligentGraphics/DiligentCore/pull/396
Thanks Mikhail!