How to create global variable in c++ that can access multiple files - c#

I used following code to provide a global variable.
namespace STR.Pref
{
public static class Pref
{
public static Lang PrimaryLang { get; set; } = Lang.Sinhala;
public static bool InsTrans { get; set; } = true;
public static HotKey Key { get; set; } = new HotKey();
}
}
So I can use following code to assign value to that global variable (any file).(without instantiating)
private static void SetValue(Pref_tempObj tempObj)
{
Pref.Pref.Key = tempObj.Key;
Pref.Pref.InsTrans = tempObj.InsTrans;
Pref.Pref.PrimaryLang = tempObj.PrimaryLang;
}
The program works perfectly,But recently I was interested in c++ so I made a decision to write that program in c++/clr with the small update. I'm bit new to c++ and I don't understand how can I accomplish this using c++.(whether using pointer or something else)

Ok, I really not recommend that but you can do following this instructions.
On a Global.h file (I mean a header will be include on every .cpp)
extern MyType MyTypeVar;
Declare on a .cpp
MyType MyTypeVar
And on every .cpp that you will include the Global.h have access to MyTypeVar.
See:
When to use extern in C++
Extern
What is the function of extern

Related

How to get UID and GID on Linux using p/invoke?

I need some simple file operations on a Linux machine, for a service installer.
The code is .NET 5.0.
My current version uses Process.Start() to execute shell commands to change the owner of files and directories and set permissions.
This is quite slow (I use asynchronous methods), especially compared to Windows equivalents.
I see libc accessible to call from .NET has methods chmod and chown, however it wants uid and gid parameters. My application doesn't know the ids, at least without using shell for it.
So far I got something like this:
const string LIBC = "libc";
[DllImport(LIBC, SetLastError = true)]
private static extern int chmod(string path, uint mode);
[DllImport(LIBC, SetLastError = true)]
private static extern int chown(string path, int owner, int group);
So... how to get those 2 ints required?
UPDATE
Why anyone see this question (especially considering its title) as duplicate of question about similar, yet different things.
I know how to change owner and permissions of Linux files in many ways. The easiest way is to use Linux shell. The quickest and easiest way is to use Mono.Posix.NETStandard library, that call libc internally.
My specific question is HOW IT IS MADE? HOW DOES IT WORK?
To be even more specific:
Here's the Linux manual page for getpwnam():
https://man7.org/linux/man-pages/man3/getpwnam.3.html
How to just call it from C# using p/invoke? I see in many examples, that when they replace char* with string it somehow magically works. I created a struct like this:
public struct PASSWD {
public string pw_name; /* username */
public string pw_passwd; /* user password */
public int pw_uid; /* user ID */
public int pw_gid; /* group ID */
public string pw_gecos; /* user information */
public string pw_dir; /* home directory */
public string pw_shell; /* shell program */
};
...and tried to use it as out parameter for the signature.
I get no error, but it just doesn't work. The struct I get is empty.
So again, we are using Platform Invoke, in C#, we are calling libc and we want to get results from a structure. As far as I googled - it's not google-able. There is only Mono source code, that uses external module that implements what I need. I suspect they made it for performance reasons, also - using some special tools, because in comments stands that the code is generated.
My question is again, how, using Linux manual page definition create appropriate method signature for C# to be able to extract those 2 integers from getpwnam().
I also was curious if something like that might already exist in .NET itself, but I guess it doesn't.
So, I got rusty with p/invoke. My issue was I forgot, that when native function returns a pointer to a structure, there is no automatic conversion, I have to leave pointer in signature, so:
[DllImport(LIBC, SetLastError = true)]
internal static extern IntPtr getgrnam(string name);
[DllImport(LIBC, SetLastError = true)]
internal static extern IntPtr getpwnam(string name);
internal struct Group {
public string Name;
public string Password;
public uint Gid;
public IntPtr Members;
}
internal struct Passwd {
public string Name;
public string Password;
public uint Uid;
public uint Gid;
public string GECOS;
public string Directory;
public string Shell;
}
Lets create fully managed .NET style types:
public sealed class GroupInfo {
public string Name { get; }
public uint Id { get; }
public string[] Members { get; }
internal GroupInfo(Syscall.Group group) {
Name = group.Name;
Id = group.Gid;
Members = GetMembers(group.Members).ToArray();
}
private static IEnumerable<string> GetMembers(IntPtr members) {
IntPtr p;
for (int i = 0; (p = Marshal.ReadIntPtr(members, i * IntPtr.Size)) != IntPtr.Zero; i++)
yield return Marshal.PtrToStringAnsi(p)!;
}
}
public class UserInfo {
public string Name { get; }
public uint Uid { get; }
public uint Gid { get; }
public string? Directory { get; }
public string? Shell { get; }
internal UserInfo(Syscall.Passwd passwd) {
Name = passwd.Name;
Uid = passwd.Uid;
Gid = passwd.Gid;
Directory = passwd.Directory;
Shell = passwd.Shell;
}
}
And it can be used like this:
public static UserInfo? GetUserInfo(string name) {
var result = Syscall.getpwnam(name);
if (result != IntPtr.Zero) return new UserInfo(Marshal.PtrToStructure<Syscall.Passwd>(result));
return null;
}
public static GroupInfo? GetGroupInfo(string name) {
var result = Syscall.getgrnam(name);
if (result != IntPtr.Zero) return new GroupInfo(Marshal.PtrToStructure<Syscall.Group>(result));
return null;
}

How to share constants in c#

I would like to store static variable in single class and use it in different classes.
What is the best practice in C#?
JavaScript example.
Just for example. I am looking for something like this:
I have single file MyStaticDataObject.js with one or more static variables.
const MyStaticDataObject = {
someKey: someValue,
anotherKey: anotherValue,
//...
}
export { MyStaticDataObject };
and I can use them in any other file:
import { MyStaticDataObject } from "./MyStaticDataObject.js";
// ... somewhere in code
console.log(`Value of someKey:`, MyStaticDataObject["someKey"]);
namespace nm1 {
internal class MyStaticDataObject {
public const string Key1 = "Value1";
public const string Key2 = "Value2";
}
}
In other classes (outside the namespace), reference the namespace using nm1; and use it. Otherwise they can be used directly without the using
using nm1;
internal class TestClass
{
private string Key1 = MyStaticDataObject.Key1;
}
Maybe late.
But this is a better way - if you need use these constants value frequently.
Declare a class with some constants.
public class ConstantsClass
{
public const string ConstName1 = "ConstValue1";
public const string ConstName2 = "ConstValue2";
public const string ConstName3 = "ConstValue3";
}
Using this class in static in code file you want. (C# 6.0 feature)
using static ConstantsClass;
namespace YourNamespace
{...
Use the constanst in the way same as it declared in local.
CallMethod(ConstName1);

Using ctypes in python to acces a C# dll's method from instance

i tried to test the examples from the website but the second one won't work.. i need to create instances and call the methods from the class where the instance is from. The first example is explained here.
It seems I don't get the right python code :/ to reach the method and attribute behind pointer object..
This is the c# dll
[ComVisible(true)]
[Guid("0000000a-000b-000c-0001-020304050607"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISample
{
// without MarshalAs(UnmanagedType.BStr), .Net will marshal these strings as single-byte Ansi!
// BStr is equivalent to Delphi's WideString
String Name
{
// this is how to add attributes to a getter's result parameter
[return: MarshalAs(UnmanagedType.BStr)]
get;
// this is how to add attributes to a setter's value parameter
[param: MarshalAs(UnmanagedType.BStr)]
set;
}
int DoSomething(int value);
}
public class Sample : ISample
{
public String Name{ get; set; }
public int DoSomething(int value)
{
return value + 1;
}
}
static class Exports
{
[DllExport]
public static void CreateSampleInstance([MarshalAs(UnmanagedType.Interface)]out ISample instance)
{
instance = new Sample{ Name = "Test" };
}
}`enter code here`
i tried in python shell
>>>import ctypes
>>>a=ctypes.cdll.LoadLibrary(source)
>>>b=a.CreateSampleInstance
>>>b
<_FuncPtr object at 0x028E65D0>
>>>b.Name
Traceback (most recent call last):
File "<pyshell#85>", line 1, in <module>
instance.Name
AttributeError: '_FuncPtr' object has no attribute 'Name'
Sure the pointer can't know the method DoSomething and the attribute Name, but how i can reach them :/
I'd recommend you take a look a IronPython (http://ironpython.net/) and specifically take a look at http://ironpython.net/documentation/dotnet/dotnet.html#id31

Calling un-managed code with pointer

I have a C# project that makes calls out to an unmanaged C++ dll. The wrapper and most of the calls are working OK, so I know that I have the basic structure of how everything ties together OK, but there is one specific call that is giving me fits. The API call requires a pointer to a structure, which contains a list of configuration data.
Here is the call:
m_status = m_XXXXBox.SetConfig(m_channelId, ref SCONFIG_LIST);
Where SCONFIG_LIST is the structure containing the data...
The issue specifically relates to SCONFIG_LIST
Here is the documentation directly from the spec for this API :
Points to the structure SCONFIG_LIST, which is defined as follows:
typedef struct
{
unsigned long NumOfParams; /* number of SCONFIG elements */
SCONFIG *ConfigPtr; /* array of SCONFIG */
} SCONFIG_LIST
where:
NumOfParms is an INPUT, which contains the number of SCONFIG elements in the array
pointed to by ConfigPtr.
ConfigPtr is a pointer to an array of SCONFIG structures.
The structure SCONFIG is defined as follows:
typedef struct
{
unsigned long Parameter; /* name of parameter */
unsigned long Value; /* value of the parameter */
} SCONFIG
Here are the 2 structures that I defined in C#:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SConfig
{
public int Parameter;
public int Value;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SConfig_List
{
public int NumOfParams;
// public List<SConfig> sconfig = new List<SConfig>(); // This throws compile time error
public List<SConfig> sconfig;
}
I know you can not have field initializers in structs, but I cant seem to figure out how to initialize the sconfig in the struct externally...
Here is snippet from the calling method
SConfig_List myConfig = new SConfig_List();
SConfig configData = new SConfig();
configData.Parameter = 0x04;
configData.Value = 0x10;
myConfig.NumOfParams = 1;
myConfig.sconfig.Add(configData);
This throws an error at runtime of "object reference not set to an instance of an object"
I understand this error because sconfig has not been initialized - I just cant figure out how to do that....
So my next thought was to get around this, I would just create the SCONFIG_LIST struct like this (without the list inside) - My reasoning for this is that I now do not have to initialize the object, and I could just make multiple calls to dll with a NumOfParams = 1, rather than NumOfParams > 1 and having the dll loop through the struct data.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct SConfig_List
{
public int NumOfParams;
public SConfig sconfig;
}
And here is how I called the method
configData.Parameter = 0x04;
configData.Value = 0x10;
myConfig.NumOfParams = 1;
myConfig.sconfig.Parameter = configData.Parameter;
myConfig.sconfig.Value = configData.Value;
m_status = m_XXXXBox.SetConfig(m_channelId, ref myConfig);
This got rid of the errors to this point, now on the the actual method that calls the dll
There are still several questions / issues surrounding the Marshalling, but here it is:
public XXXXErr SetConfig(int channelId, ref SConfig_List config)
{
unsafe
{
IntPtr output = IntPtr.Zero;
IntPtr input = Marshal.AllocHGlobal(Marshal.SizeOf(config));
Marshal.StructureToPtr(config, input, true);
XXXXErr returnVal = (XXXXErr)m_wrapper.Ioctl(channelId, (int)Ioctl.SET_CONFIG, input, output);
return returnVal;
}
}
This gets past all of the initial setup without error, but when I try to actually invoke the dll I get an error : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I know this is a mouthful, and I really don't even know exactly what to ask as I am sure there are multiple issues within this post, but any ideas on getting me on the right track?
I have tried so many things at this point I am at a loss, and I just need some direction. I am not looking for a "do this for me" type answer, but rather an explanation and maybe some pointers on getting this done. As with all things, I am sure there are multiple ways of accomplishing the task - maybe a way that works, but is not good form, and a longer more complicated way that may be "better practice"
Any and all suggestions / comments will be greatly appreciated. And if I excluded any relevant data that is required to help me solve this riddle let me know and I will provide what I can.
I want to thank the responses so far.
I have been trying every combination to try and resolve this myself but I have not had any luck so far. I have found quite a few ways that do NOT work, however :-)
I have tried various combinations of "unsafe" - "MarshalAs", "StructLayout" and several other things I found on the web, now I am begging for mercy.
I have successfully implemented several other calls to this unmanaged dll, but all of them use simple integer pointers etc. My problem is passing the pointer to a Struct containing an array of another struct. If you look at the very top of my original question you can see the documentation from the dll and how it wants thing structured. There is NO return value, I am merely trying to pass some configuration settings to a device through this dll.
I am going to post a framework of my entire project so that maybe I can get someone to hold my hand through this process, and hopefully help others in the future trying to solve this type of issue as well.
Here is skeleton of Wrapper (not all functions displayed)
using System;
using System.Runtime.InteropServices;
namespace My_Project
{
internal static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
internal class APIDllWrapper
{
private IntPtr m_pDll;
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int APIIoctl(int channelId, int ioctlID, IntPtr input, IntPtr output);
public APIIoctl Ioctl;
//extern ā€œCā€ long WINAPI APIIoctl
//(
//unsigned long ChannelID,
//unsigned long IoctlID,
//void *pInput,
//void *pOutput
//)
public bool LoadAPILibrary(string path)
{
m_pDll = NativeMethods.LoadLibrary(path);
if (m_pDll == IntPtr.Zero)
return false;
pAddressOfFunctionToCall = NativeMethods.GetProcAddress(m_pDll, "APIIoctl");
if (pAddressOfFunctionToCall != IntPtr.Zero)
Ioctl = (APIIoctl)Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall,
typeof(APIIoctl));
return true;
}
public bool FreeLibrary()
{
return NativeMethods.FreeLibrary(m_pDll);
}
}
}
And Here is the class that defines the hardware I am trying to communicate with
namespace My_Project
{
public class APIDevice
{
public string Vendor { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
}
Interface
using System.Collections.Generic;
namespace My_Project
{
public interface I_API
{
APIErr SetConfig(int channelId, ref SConfig_List config);
}
}
The actual Class containing the API Code - this is where the error is, I know that how I have the IntPtrs now is Not correct - But this displays what I am trying to do
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace My_Project
{
public class API : I_API
{
private APIDevice m_device;
private APIDllWrapper m_wrapper;
public APIErr SetConfig(int channelId, ref SConfig_List config)
{
IntPtr output = IntPtr.Zero;
IntPtr input = Marshal.AllocHGlobal(Marshal.SizeOf(config));
Marshal.StructureToPtr(config, input, true);
APIErr returnVal = (APIErr)m_wrapper.Ioctl(channelId, (int)Ioctl.SET_CONFIG, input, output);
return returnVal;
}
}
}
Here is class containing the definitions for the Structs I am using
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace My_Project
{
public enum APIErr
{
STATUS_NOERROR = 0x00,
ERR_BUFFER_EMPTY = 0x10,
ERR_BUFFER_FULL = 0x11,
ERR_BUFFER_OVERFLOW = 0x12
}
public struct SConfig
{
public int Parameter;
public int Value;
}
public struct SConfig_List
{
public int NumOfParams;
public SConfig[] sconfig;
public SConfig_List(List<SConfig> param)
{
this.NumOfParams = param.Count;
this.sconfig = new SConfig[param.Count];
param.CopyTo(this.sconfig);
}
}
}
And finally - the actual application calling the dll through the wrapper
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using My_Project;
namespace Test_API
{
public class Comm
{
private I_API m_APIBox;
APIErr m_status;
int m_channelId;
bool m_isConnected;
public Comm(I_API apiInterface)
{
m_APIBox = apiInterface;
m_isConnected = false;
m_status = APIErr.STATUS_NOERROR;
}
public bool ConfigureDevice()
{
SConfig tempConfig = new SConfig();
tempConfig.Parameter = 0x04;
tempConfig.Value = 0x10;
SConfig_List setConfig = new SConfig_List(tempConfig);
m_status = m_APIBox.SetConfig(m_channelId, ref setConfig);
if (m_status != APIErr.STATUS_NOERROR)
{
m_APIBox.Disconnect(m_channelId);
return false;
}
return true;
}
}
}
You cannot marshal List<>, it must be an array. An array is already marshaled as a pointer so you don't have to do anything special. Go easy on the Pack, no need for the unsafe keyword.
You could add a constructor to the struct to make it easy to initialize it from a List<>. Like this:
[StructLayout(LayoutKind.Sequential)]
public struct SConfig {
public int Parameter;
public int Value;
}
[StructLayout(LayoutKind.Sequential)]
public struct SConfig_List {
public int NumOfParams;
public SConfig[] sconfig;
public SConfig_List(List<SConfig> param) {
this.NumOfParams = param.Count;
this.sconfig = new SConfig[param.Count];
param.CopyTo(this.sconfig);
}
}
To initialize list you just have to add line:
myConfig.sconfig = new List<SConfig>()
before you start adding elements into it.
I started another thread because I was asking the wrong question due to my inexperience
The working solution is here
Marshal array of struct and IntPtr
Thanks for the help
-Lee

Pass a variable from one file to another c#

I have two .cs files (Hex2Bin.cs and Program.cs) and I want to pass the variable end_addr from Program.cs to Hex2Bin.cs
My code in Program.cs:
class Program
{
enum to_exit {
exit_ok = 0,
exit_invalid_args,
exit_to_few_args,
exit_invalid_input_file,
exit_invalid_args_file,
exit_permission_denied,
exit_unexpected_eof
};
// class value holders
static String args_file_name = "";
static String in_u1_name = "";
static String in_u22_name = "";
static String out_name = "";
static short end_addr = 0x0000; // 4-digit Hexadecimal end address
static Byte[] version_code = { 0, 0, 0, 0 }; // 3 bytes version, 1 for extra info
}
Is there anyway I could do this? I know how to do it in c, but I'm very new to c#. Thanks.
C# doesn't work like C with respect to static variables. You can make the variable end_addr available outside the Program class by making it a public field. By default, fields are private.
public static end_addr = 0x0000;
And then it can be accessed like so:
var x = Program.end_addr;
However, I would recommend that you spend a little more time familiarizing yourself with C# idioms and conventions. It seems like your still thinking about C# in terms of C, and they are very different.
if you declare the variable like this:
public static short end_addr = 0x0000;
then from another class you can use it like this:
Program.end_addr
but don't do this, is not object oriented!
if your class Hex2Bin is used/invoked by the Main method of Program class, you should be able to pass your variables as input parameters of the methods you call or set them as properties of the classes/objects you use...
It's enough to mark end_addr as public like so
public static short end_addr = 0x0000;
Then you can access it from anywhere like this
Program.end_addr
It's a better practice though to use properties rather than fields for exposing data.
// Property
public static short end_addr { get; private set; }
// Constructor
public Program()
{
// Initialize property value.
end_addr = 0x0000;
}
You're talking about 'files' but what you really want to do is to pass data from your program's entry point (Program.cs) to a an object of a class (or method of static class) that will process the data, am I right?
If so, this should be pretty simple. You either have to modify your Program.cs and create an instance of the class (the one from Hex2Bin.cs) like this
...
Hex2Bin hex2bin = new Hex2Bin( end_addr );
...
I assume that the Hex2Bin is as follows:
public class Hex2Bin
{
private short endAddress;
public Hex2Bin( short endAddress )
{
this.endAddress = endAddress;
}
}
this will allow you to use the value of end_addr from Program.cs
Another approach is to pass it directly to the method that will make use of it:
Hex2Bin.Method(end_addr);
and in the Hex2Bin file:
public static void Method(short endAddress)
{
//... do the work here
}
Given your background in C, I think you may be mixing runtime with compile time issues.
However, in Hex2Bin.cs, you can create a static method that updates a static variable.
class Hex2Bin
{
static short end_addr = 0x0000;
static void updateEndAddr(short endAddr)
{
end_addr = endAddr;
}
}

Categories

Resources