How to use unsafe context in Unity - c#

I want to use c++ code in c# for Unity using CLR.
The program works properly outside of unity, but inside of engine it gives me an error:
"cs0227: unsafe code requires the 'unsafe' command line option to be specified"
I am really confused, because the project builds successfully in visual studio (without any errors or warnings). I have "allow unsafe" button activated.
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class newspawn_real : MonoBehaviour {
void Start () {
unsafe
{
fixed (int * p = &bam[0, 0, 0])
{
CppWrapper.CppWrapperClass controlCpp = new CppWrapper.CppWrapperClass();
controlCpp.allocate_both();
controlCpp.fill_both();
controlCpp.fill_wrapper();
}
}
}
// ...
}

You have to explicitly enable unsafe code in Unity. You can follow the steps below:
1. First step, Change Api Compatibility Level to .NET 2.0 Subset.
2. Create a file in your <Project Path>/Assets directory and name it smcs.rsp then put -unsafe inside that file. Save and close that file.
Close and reopen Visual Studio and Unity Editor.
You must restart both of them.
It's worth noting that even after doing this and restarting both Unity and Visual Studio, if the problem is still there,
Rename the smcs.rsp file to csc.rsp, gmcs.rsp or mcs.rsp
Restart Unity Editor and Visual Studio each time until you get one that works. For more details about the file name to use, refer to Platform Dependent Compilation documentation.
Simple C# unsafe code that compiles after this.
public class newspawn_real : MonoBehaviour
{
unsafe static void SquarePtrParam(int* p)
{
*p *= *p;
}
void Start()
{
unsafe
{
int i = 5;
// Unsafe method: uses address-of operator (&):
SquarePtrParam(&i);
Debug.Log(i);
}
}
}

update:
on unity 2019 and forward, we don't have the 2.0 subset.
use 2.0 Standard.
and although mcs.rsp works, there is a warning noting that mcs is obsolete, and we should use csc.rsp instead.
but it actually works !

Related

How can I add a static 'Main' method suitable for an entry point?

I am getting an error on my code that says "Error CS5001
Program does not contain a static 'Main' method suitable for an entry point"
I am coding in C# using Microsoft Visual Studio and .NET. This is my code.
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System;
class projectsummer
{
[CommandMethod("OpenDrawing", CommandFlags.Session)]
public static void OpenDrawing()
{
string strFileName = "C:\\DRAFT.dwg";
DocumentCollection acDocMgr = Application.DocumentManager;
if (File.Exists(strFileName))
{
acDocMgr.Open(strFileName, false);
}
else
{
acDocMgr.MdiActiveDocument.Editor.WriteMessage("File " + strFileName +
" does not exist.");
}
}
}
I am not sure how to go about this error. Thank you!
Looking at this post and your previous question, let's try and break down what's going on.
You created a new Console application in Visual Studio. You did not tick "Do not use top level statements". This gave you a Program.cs file that was essentially empty (there was no "Main" method visible).
You erased the Hello World code given to you, and went to make a static method - the code from your previous question.
Damien_The_Unbeliever commented that based on the error, you put your method inside a "top level statement" file, and to put your method inside a class.
You wrap your method (which is still inside Program.cs) in a class, and now suddenly you get a Can't Find Entry Point error.
User Ryan Pattillo posted a great explanation of the original issue - where your method was "by itself" in the Program.cs file. You should follow their advice, but you should also ensure that this class is in its own file.
You should end up with this:
Program.cs
// this is the entire contents of the file
using ConsoleApp1;
ProjectSummer.OpenDrawing();
ProjectSummer.cs
using System.IO;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System;
namespace ConsoleApp1
{
public class ProjectSummer
{
[CommandMethod("OpenDrawing", CommandFlags.Session)]
public static void OpenDrawing()
{
// ...
}
}
}
Change ConsoleApp1 to the name of your project.
The entry point of your application, which right now is the only file that has "top level statements", remains Program.cs, thus you fix the Can't Find Entry Point error.
Another adjustment you can make, which seeing you're new to C# might be useful, is to not use top level statements at all. Modify your Program.cs to this:
namespace ConsoleApp1
{
internal static class Program
{
// this is your program's entry point
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
ProjectSummer.OpenDrawing();
}
}
}
Change ConsoleApp1 to the name of your project.
You cannot use the AutoCAD .NET API out of process. To be able to use the AutoCAD .NET libraries, you have to build a "class library" project (DLL) and NETLOAD this DLL from a running AutoCAD process. See this topic about in-process vs out-of-process and you can start from this other one to see how to create an AutoCAD .NET project.

Unity- vs code error: if ($?) { dotnet run $Player_Movement } (Solved)

Hi I am getting "cd "c:\Users\UMUT\Desktop\Unity Projects\Newest\Assets" ; if
($?) { dotnet run $Player_Movement }" message and I get this error message "Couldn't find a project to run. Ensure a project exists in C:\Users\UMUT\Desktop\Unity Projects\Newest\Assets, or pass the path to the project using --project." in my Vs code Unity project. İn my another old project I have a C# script named Player_Movement but I am getting this error in my new Unity Project when I try to debug the project.I downloaded C# extension.I downl Any solutions or reason why it is happening?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class New : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("hi");
}
// Update is called once per frame
void Update()
{
}
}
I resetted Vs code settings and change my C# extension to older version and error fixed.
I reseted Vs code settings to default and my problem is fixed.

No errors appear in Visual Studio or VSCode using C#

Image of my code in Visual Studio
Forgive me, I am somewhat new to coding, so maybe this is a dumb question.
I am learning how to use Unity and I am using Visual Studio to edit my code (C#).
For some reason, the red squiggly lines will not appear for most errors. It won't even recognize that there is an error.
The only error I have had it recognize is a missing semicolon.
For example, I can say a string is equal to a float (as seen below: characterName = itemDurability;), and it had not issue with this in either Visual Studio or VSCode. I can have an item defined as multiple different things, and still no errors. Of course Unity will tell me there is a problem when the code loads, but I'd like to know as I'm writing it.
I have tried updating and reinstalling, but nothing works. I cannot find anything online that has helped me with this problem.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
string characterName;
characterName = "Duncan";
int characterLevel = 5;
int experience = characterLevel * 5;
float itemDurability = 1.527f;
experience = (int)itemDurability;
characterName = itemDurability;
bool equippable = false;
if (itemDurability > 1f)
{
experience = (int)(itemDurability * 1.5f) / characterLevel;
}
}
}
From your screen-shot, it appears that you have opened the .cs (using VS) by double clicking on it or that file is not part(or excluded) of your Project , essentially you're opening the file for editing and using VS like a text editor as Indicated by Miscellaneous Filesand Attach Debugger symbol from your snap
Ensure that File is added to your Project with SolutionExplorer window and BuildAction=C# Compiler. See example
The only error I have had it recognize is a missing semicolon.
Visual Studio IDE interpreted the file as C# from the .cs extensions, and because of which it will look for ; and a semicolon is required at the end of every statement in C#.
For some reason, the red squiggly lines will not appear for most errors
Compiler is only doing a syntax check and not checking the semantics of the statements, for that matter compiler will even accept something like
Myclass a = new MyClass(); even though MyClass is not defined

Unity command-line build requires UnityEditor.BuildPipeline, but builds fail for missing 'UnityEditor' reference

I am presently trying to create a batch file for a command-line build of a simple Unity project.
Current environment is:
* Windows 10
* Unity 2017.4.19f1 (Personal)
* Offline network
The project consists of just a simple scene that works fine in the UnityEditor. After failing to get a good build, I've stripped down my build script and batch file to the following:
BareBoneBuild.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
namespace Assets.BuildScripts
{
class BareBoneBuild
{
private static string windowsBuildFolderPath = "G:/dev/projects/SimpleProject";
static void PerformBuild()
{
string[] scenes = { "Assets/Scenes/DetectionTest.cs" };
BuildPipeline.BuildPlayer(scenes, windowsBuildFolderPath + "/junk.exe", BuildTarget.StandaloneWindows, BuildOptions.None);
}
}
}
BareBoneBuild.bat
title Unity Build
echo Launching Unity Build...
"C:\Program Files\Unity\Editor\Unity.exe" ^
-batchmode ^
-projectPath G:\dev\projects\SimpleProject ^
-executeMethod Assets.BuildScripts.BareBoneBuild.PerformBuild ^
-quit ^
-logFile G:\dev\projects\SimpleProject\logs\BareBoneBuild.log
echo Build Finished!
PAUSE
BareBoneBuild.log (snippet)
...
-----CompilerOutput:-stdout--exitcode: 1--compilationhadfailure: True--outfile: Temp/Assembly-CSharp.dll
Compilation failed: 1 error(s), 0 warnings
-----CompilerOutput:-stderr----------
Assets/BuildScripts/BareBoneBuild.cs(6,7): error CS0246: The type or namespace name `UnityEditor' could not be found. Are you missing an assembly reference?
-----EndCompilerOutput---------------
- Finished compile Library/ScriptAssemblies/Assembly-CSharp.dll
Assets/BuildScripts/BareBoneBuild.cs(6,7): error CS0246: The type or namespace name `UnityEditor' could not be found. Are you missing an assembly reference?**
(Filename: Assets/BuildScripts/BareBoneBuild.cs Line: 6)
DisplayProgressNotification: Build Failed
Error building Player because scripts had compiler errors
(Filename: Line: -1)
...
EVERY tutorial, blog, youtube video, forum
* https://docs.unity3d.com/2017.4/Documentation/Manual/CommandLineArguments.html
* http://jonathanpeppers.com/Blog/automating-unity3d-builds-with-fake
* https://www.youtube.com/watch?v=4J3SmhGxO1Y
* others...that I don't have the links to
I've viewed states that BuildPipeline.BuildPlayer is the way to build a project from the command-line. BuildPipeline is inside the UnityEditor library.
What am I doing wrong? I'm still new to Unity, so any obvious solution is probably correct.
Thanks in advance for any guidance!
You can't have using UnityEditor; in a build. It is stripped of.
You only need this available in an editor script and not in a build so:
Either use #if pre-processors wrapping everything using it like
#if UNITY_EDITOR
using UnityEditor;
#endif
...
#if UNITY_EDITOR
// anything using UnityEidtor e.g. the method or entire class
#endif
or in your case simply move the entire script into a folder called Editor which strippes of the entire script for a build (see Special folder names).
This is actually also mentioned - though not well explained - by your link:
Then you would need a class in your Unity project in an Editor folder such as this Android example:
or in newer Unity versions you can put it in a separate folder (with any name) and create an AssemblyDefinition and configure it so it is only compiled for the UnityEditor (see in particular Creating an assembly for Editor code)

Detect c# version at compile time

I have an old line of c# code that looks basically like this:
foo.set_Parent(parent);
It has compiled fine for years. Now in VS2015 I get the error:
CS0571 'Foo.Parent.set': cannot explicitly call operator or accessor
So I can rewrite the line as:
foo.Parent=parent;
This builds fine in VS2015, but in VS2013 it gives the error:
'Foo.Parent' is not supported by the language; try directly calling
accessor methods 'Foo.get_Parent()' or Foo.set_Parent(Foo)'
So the simple fix is to simply ifdef these two lines based upon which version of the compiler is running. But how do you detect which version of the compiler is executing?
And for the record, no, I can't just dictate that everyone on the team simultaneously upgrades to VS2015.
Additional info -
For everyone smelling a rat, I'll go ahead and drag out the ugly truth, although I don't think it will change much of anything. The class Foo is from an ancient Borland assembly that is all bound up in Delphi (and yes, we're migrating away but not there yet). So the actual code, that compiles up to VS2013, looks like this:
using Borland.Vcl;
using RepGen;
using SnapReportsForm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace MigrantCOM {
[ComVisible(true)]
[Guid("48245BA3-736B-4F98-BDC5-AD86F77E39F4")]
[ProgId("MigrantCOM.Exports")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class MigrantCLRExports { // : MarshalByRefObject
public string Test(string s) { return s+s; }
}
[ComVisible(true)]
[Guid("1154D364-B588-4C31-88B9-141072303117")]
[ProgId("MigrantCOM.SnapRepCOM")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SnapRepCOM {
TRepGen repGen;
TStringList snapRefs=new TStringList();
TForm parent=new TForm(null);
TMemo designerMemo;
List<TReference> references=new List<TReference>();
TRunAsSnapContext runAsSnapContext=new TRunAsSnapContext();
public SnapRepCOM() {
designerMemo=new TMemo(parent); designerMemo.set_Parent(parent);
...
}
So the class being instantiated is Borland.Vcl.TMemo which is part of the old Delphi assembly.
I'm leaving this as an answer, linking an image will fit better here than in a comment.
So if you want to use VS 2015 but still use the same good ol' version of the C# language that worked for years, you can configure your project to target a specific version:
This adds <LangVersion>5</LangVersion> in the csproj.

Categories