SharpGenTools icon indicating copy to clipboard operation
SharpGenTools copied to clipboard

Minimal examples fail to generate or crash with NullReferenceException

Open roy-t opened this issue 2 years ago • 9 comments

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?

roy-t avatar Jun 25 '22 12:06 roy-t

I assume you saw #101? That appears to be the same issue, and the fix mentioned there worked for me.

CaiB avatar Mar 13 '23 03:03 CaiB

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!

roy-t avatar Mar 13 '23 20:03 roy-t

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.

CaiB avatar Mar 13 '23 20:03 CaiB

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.

roy-t avatar Mar 13 '23 20:03 roy-t

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.

CaiB avatar Mar 13 '23 21:03 CaiB

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.

roy-t avatar Mar 13 '23 21:03 roy-t

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 avatar Mar 13 '23 21:03 roy-t

@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

MikhailGorobets avatar May 21 '23 01:05 MikhailGorobets

Thanks Mikhail!

roy-t avatar May 27 '23 17:05 roy-t