Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal examples fail to generate or crash with NullReferenceException #221

Open
roy-t opened this issue Jun 25, 2022 · 9 comments
Open

Comments

@roy-t
Copy link

roy-t commented Jun 25, 2022

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?

@CaiB
Copy link

CaiB commented Mar 13, 2023

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

@roy-t
Copy link
Author

roy-t commented Mar 13, 2023

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!

@CaiB
Copy link

CaiB commented Mar 13, 2023

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.

@roy-t
Copy link
Author

roy-t commented Mar 13, 2023

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.

@CaiB
Copy link

CaiB commented Mar 13, 2023

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.

@roy-t
Copy link
Author

roy-t commented Mar 13, 2023

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
Copy link
Author

roy-t commented Mar 13, 2023

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?

@MikhailGorobets
Copy link

@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
DiligentGraphics/DiligentCore#396

@roy-t
Copy link
Author

roy-t commented May 27, 2023

Thanks Mikhail!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants