I've been playing around with OpenTK and it's been great following along the examples/tutorials.
I really want to have the OpenGL render in a smaller portion of the Window so I've been trying to use GLWpfControl, and I want to do it without XAML but I can't get it running properly.
I've been trying to get it to run through dotnet CLI from a console template. Here is my code:
using System;
using System.Windows;
using OpenTK.Wpf;
using OpenTK.Graphics.OpenGL;
namespace Test {
public class MyWindow : Window {
[STAThread]
public static void Main() {
Application app = new Application();
app.Run(new MyWindow());
}
public MyWindow() {
GLWpfControl wpfControl = new GLWpfControl();
wpfControl.Render += GLWpfOnRender;
this.Content = wpfControl;
var settings = new GLWpfControlSettings();
wpfControl.Start(settings);
}
void GLWpfOnRender(TimeSpan delta) {
Console.WriteLine(delta.TotalMilliseconds);
GL.ClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
}
}
}
I'm expecting the control to be rendered with a red color, however it is black. It isn't black without the call to Start() and GLWpfOnRender is being called repeatedly after the call to Start().
Here is the .csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<RootNamespace>test_2</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenTK" Version="4.7.4" />
<PackageReference Include="OpenTK.GLWpfControl" Version="4.2.2" />
</ItemGroup>
</Project>
I think I'm missing something that might be done when you call InitializeComponent() while using XAML. I've been doing a lot of reading but I'm stumped.
here's a link to what I'm trying to replicate:
https://github.com/opentk/GLWpfControl/tree/aefe945f65e4659bd6f9f82083a4a746c2fb03fc/src
Edit:
I've inherited and overriden GLWpfControl, and able to use the DrawingContext to print text and do all sorts of stuff. So GL is not working with the control for whatever reason?
Okay I got it working. Turns out there are some known issues with two graphics cards / Intel HD graphics. I had my GPU disabled. Enabled, it works fine. My own fault for not checking issues tab on github in the first place.
I'm trying to migrate existing library to .NET Core to be able to run it under Linux.
When using the library in Linux, the runtime throws System.ArgumentException:
An unhandled exception of type 'System.ArgumentException' occurred in ConsoleApp6.dll: 'Type 'ConsoleApp6.MyStruct' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.'
Stack trace:
at System.Runtime.InteropServices.Marshal.OffsetOfHelper(IRuntimeFieldInfo f)
at ConsoleApp6.Program.Main(String[] args) in C:\Users\user\source\repos\ConsoleApp6\ConsoleApp6\Program.cs:line 10
In Windows, it works as expected.
Here a simple Console app that demonstrates the issue:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine((Int32) Marshal.OffsetOf<MyStruct>("buffer"));
Console.ReadLine();
}
}
[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)]
public struct MyStruct
{
public Int16 number;
public byte[] buffer;
}
}
Here is the csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.7.12" />
</ItemGroup>
</Project>
I expect the output to be 4 in Windows and Linux, but in Linux it throws the above exception.
In .NET Core, you can't use OffsetOf<T>, per the Docs:
OffsetOf(Type, String)
Returns the field offset of the unmanaged form of the managed class.
OffsetOf<T>(String)
[Supported in the .NET Framework 4.5.1 and later versions]
Returns the field offset of the unmanaged form of a specified managed class.
In order for your code to work on Linux, you'll need to use the OffsetOf(Type, String) overload instead.
Console.WriteLine((Int32) Marshal.OffsetOf(typeof(MyStruct),"buffer"));
I've dug deeper into the CLR source code; and there's no apparent reason why your code shouldn't work on Linux. The defining characteristic of it being Marshalable, that I can see, is whether or not it's an Interface.
I'm going to dig deeper -- I see source code in the vm folder; but I'd also expect to see implmentation source code for each target environment, and I don't see that.
I am trying to make a simple WinForm tool to assist with code generation, and I was wondering if it was possible to get the Assembly of one project into a different one that presides in a different solution. I want the form to show all of the classes and then properties for each class, and the easiest/best way I can think of doing that is like:
private Type[] GetTypesInNamespace(Assembly assembly, string nameSpace)
{
return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray();
}
If the user selects a .csproj file, is it possible to get the Assembly? Or is there a different way to get the classes/properties without recursively searching the project folder and parsing the files?
The csproj file will contain the assembly name and the output directory.
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AssemblyName>MyAppAssemblyNameOnly</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
</PropertyGroup>
</Project>
You'll have to add .dll suffix to it to get the actual file name.
The Output Path can be found in the different Configuration <PropertyGroup> nodes.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
</PropertyGroup>
There's a couple of problems I can think of right off the bat.
The DLL may not be built and so it won't exist.
There are many different configurations with there being Debug and Release by default. You'll have to decide which one to look for.
For ease, you may just want to make the user feed you a DLL if the project is not part of the solution and you don't actually need anything else.
You can also look into Roslyn and parse the files with Roslyn to get you all of the information you need too.
Here's an example straight from their page. Seems super simple and straightforward. Kind of larger than I want, but don't want to just give a single link-only suggestion.
class Program
{
static void Main(string[] args)
{
SyntaxTree tree = CSharpSyntaxTree.ParseText(
#"using System;
using System.Collections;
using System.Linq;
using System.Text;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(""Hello, World!"");
}
}
}");
var root = (CompilationUnitSyntax)tree.GetRoot();
var firstMember = root.Members[0];
var helloWorldDeclaration = (NamespaceDeclarationSyntax)firstMember;
var programDeclaration = (ClassDeclarationSyntax)helloWorldDeclaration.Members[0];
var mainDeclaration = (MethodDeclarationSyntax)programDeclaration.Members[0];
var argsParameter = mainDeclaration.ParameterList.Parameters[0];
}
}
I want to use TextWriter.Synchronized method in my app. My target framework is: netcoreapp1.1.
This is the program I am trying to compile:
using System;
using System.IO;
namespace program
{
class Program
{
static void Main(string[] args)
{
using (var log = File.CreateText("out.log"))
{
var syncedLog = TextWriter.Synchronized(log);
}
}
}
}
This is my csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
</Project>
Unfortunatelly, this does not work:
> dotnet run
Program.cs(12,47): error CS0117: 'TextWriter' does not contain a definition for 'Synchronized'
How do I fix this?
Since TextWriter.Synchronized does not exist on .Net Core 1.1, you will have to implement it yourself. As a start, you can use the .Net Core 2.0 implementation. You won't be able to use that code directly, because it extensively uses [MethodImpl(MethodImplOptions.Synchronized)], which is also not supported on .Net Core 1.1. But you can replace that with lock (this) in each such method.
I have the following code contract:
public void F(string x)
{
Contract.Requires(!string.IsNullOrWhiteSpace(x));
throw new NotImplementedException();
}
When compiling, I get the following warning:
warning CC1036: Detected call to method 'System.String.IsNullOrWhiteSpace(System.String)' without [Pure] in contracts of method [...]
How to deal with it?
What's odd, is that I'm also using string.IsNullOrEmpty, which isn't marked as [Pure] as well, in other contracts and the rewriter does not have a problem with that.
My Contract Rewriter's Version is 1.9.10714.2.
This is the relevant part from the implementation of String class I'm using (retrieved from metadata):
#region Assembly mscorlib.dll, v4.0.0.0
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\mscorlib.dll
#endregion
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
namespace System
{
// Summary:
// Represents text as a series of Unicode characters.To browse the .NET Framework
// source code for this type, see the Reference Source.
[Serializable]
[ComVisible(true)]
public sealed class String : IComparable, ICloneable, IConvertible, IEnumerable, IComparable<string>, IEnumerable<char>, IEquatable<string>
{
// [...]
//
// Summary:
// [...]
public static bool IsNullOrEmpty(string value);
//
// Summary:
// [...]
public static bool IsNullOrWhiteSpace(string value);
Why is the [Pure] attribute missing?
Here we have two points:
1. Why is the [Pure] attribute missing in string class for IsNullorWhiteSpace function?
2. How to resolve the CC1030 warning issue?
I will try to discuss both.
1. Why is the [Pure] attribute missing? It's not missing, metadata does not seem to be showing this.
This may not be marked as Pure in previous version of .NET FX as, they were saying:
Yes, we need to make our checker sensitive to the disable pragma...
Sigh.
We currently don't have that implemented, but I've added it to our
work list.
Refer to the 5 year old discussion here.
But this has been marked as Pure in latest FX (4.6.1), Refer to .NET Framework 4.6.1, the new string class code.
[Pure]
public static bool IsNullOrWhiteSpace(String value) {
if (value == null) return true;
for(int i = 0; i < value.Length; i++) {
if(!Char.IsWhiteSpace(value[i])) return false;
}
return true;
}
Then Why CC1036?
This warning "CC1036" is from CodeContracts, developers have open this issue yesterday only (refer here).
Now why metadata is not spitting up Pure attributes, this is a different question, like for Equals method, Pure is added but only SecuritySafeCritical is displayed in metadata code.
[SecuritySafeCritical]
public static bool Equals(String a, String b, StringComparison comparisonType);
The same problem applies to Invariant(). Given the following code, the
same warnings are displayed:
private string testString = "test";
[ContractInvariantMethod]
private void TestInvariant()
{
Contract.Invariant(!string.IsNullOrWhiteSpace(testString));
}
How to resolve?
As others are also suggesting, create another method, mark it as Pure and call this in your contract condition.
Going through a pure delegate will make the warning go away. Predicate<T> is already marked pure, so you can just use that to work around the bug:
// Workaround for https://github.com/Microsoft/CodeContracts/issues/339
public Predicate<string> IsNullOrWhiteSpace = string.IsNullOrWhiteSpace;
public void F(string x)
{
Contract.Requires(!IsNullOrWhiteSpace(x));
throw new NotImplementedException();
}
Although kind of ugly, you can wrap the function string.IsNullOrWhiteSpace with an extension method and mark this new function as Pure.
I just encountered the exact same problem. I'm using VS2015, so it does not seem to be related to VS version. I also tested the exact same code on .NET 4.0, 4.5.1 and 4.6, without getting the warning.
Like others have commented before me, the IsNullOrWhiteSpace is marked as [Pure] in .NET 4.6.1, and additionally should by default be considered pure by Code Contracts because it is in the System.String namespace. This makes it look like a bug, so I have submitted an issue to Code Contracts about this, so with some luck we will see an official answer soon.
While we wait for an answer, it is possible (like #Jaco suggests) to wrap it in an extension method and mark it as Pure yourself. Optionally, you can suppress the warning for that particular method like this:
[SuppressMessage("Microsoft.Contracts", "CC1036", Justification = "string.IsNullOrWhiteSpace is Pure")]
... but note that this will also suppress this warning from other Contract definitions in the same method.
Actually, this is a problem with the way .NET 4.6+ is compiled. See this GitHub pull request.
I was able to work around this by modifying the following file(s):
For Visual Studio 2013:
C:\Program Files (x86)\Microsoft\Contracts\MsBuild\v12.0\Microsoft.CodeContracts.Targets
For Visual Studio 2015:
C:\Progarm Files (x86)\Microsoft\Contracts\MsBuild\v14.0\Microsoft.CodeContracts.Targets
In both files, ensure the <Otherwise> child element of the first <Choose> element has the following content shown below:
...
<Choose>
<When Condition="'$(TargetFrameworkIdentifier)' == 'Silverlight'">
...
</When>
<Otherwise>
<Choose>
<When Condition="'$(TargetFrameworkVersion)' == 'v4.0">
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.0</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</When>
<When Condition="'$(TargetFrameworkVersion)' == 'v4.5'">
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</When>
<When Condition="'$(TargetFrameworkVersion)' == 'v4.5.1'">
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</When>
<When Condition="'$(TargetFrameworkVersion)' == 'v4.5.2'">
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</When>
<When Condition="'$(TargetFrameworkVersion)' == 'v4.6'">
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</When>
<When Condition="'$(TargetFrameworkVersion)' == 'v4.6.1'">
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v4.5</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<CodeContractsReferenceAssemblyLibPath>$(CodeContractsInstallDir)Contracts\.NETFramework\v3.5</CodeContractsReferenceAssemblyLibPath>
</PropertyGroup>
</Otherwise>
</Choose>
</Otherwise>
</Chose>
...
After making these changes to these files (per the GitHub pull request referenced above), I no longer received Code Contracts static analysis warnings for the use of String.IsNullOrWhiteSpace.
It should be noted that the referenced pull request has been merged into the main code for Code Contracts up on GitHub; they just haven't made a new release containing these changes yet.
Also, for those concerned about changing "system files", don't be. When the next version of Code Contracts is released, it will install updated versions of these files--and hopefully the changes will be included, and all will be right with the world. (Unless, of course, the changes aren't included--in which case, you'll be coming back here to reference this post to make those changes again ;) lol.)