Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

char, sbyte, byte and uint with arrays and pointers

3.67/5 (3 votes)
4 Jun 2024CPOL5 min read 13.3K  
There are new convertions for C#
For example WinAPI+DirectX ( TerraFX.Interop.Window ) and cross-platform for Xlib ( TerraFX.Interop.Xlib ) or xcb ( DeafMan1983.Interop.xcb - WIP ) Any convertion functions can you use easy write similar than you waste long time with hard-coded functions.

Introduction

I would like to show about modern convertion functions for C# and they can work everything if you use SDL2 ( DeafMan1983.Interop.SDL2 ) / SDL3 ( DeafMan1983.Interop.SDL3, WIP ) or GTK4/5 and pure code with Qt6 ( without Qt6 frameworks, only hard-coded sources with WinAPI and X11, xcb and other windowing system runtimes for Linux, macOS and Android, also iOS ( I am not sure ))

Background

Since I am supervising about NativeAot used dotnet apps like AppWithPlugins and PaintNet ( WIP ) and I have a lot of works with modern convertion functions like you have not problem with WinAPI without fixed-statements.

Using the Code

**NEW**
Explanations of char[], char*, char**, char*[] and char[][]:
char[] StringToCharArray(string intput) It works like string.ToCharArray();
string CharArrayToString(char[] ary) It likes new string(char[] ary);
char* StringToCharPointer(string intput) It is really special pointer for char* with TerraFX.Interop.Windows unlike in C/C++ example wchar* or TChar*
string CharPointerToString(char* ptr) is a back converter unlike in C/C++ std::string
char** StringArrayToCharDoublePointer(string[] inputs) like in C/C++ wchar** argv
string[] CharDoublePointerToStringArray(char** dblPtr) like in C/C++ wchar** argv
char*[] CharDoublePointerToCharPointerArray(char** dblPtr) convert to char*[]
char** CharPointerArrayToCharDoublePointer(char*[] ptrAry) convert to char**
char[][] CharPointerArrayToCharDoubleArray(char*[] ptrAry) is an advanced array length of char[] and can work everything like in any C/C++. Because I have seen about char[][] example int main(int argc, char** argv) { ... } like Quake 2 or Half-Life have to use char[][] from CommandLine or any functions but I will look for more functions.
char*[] CharDoubleArrayToCharPointerArray(char[][] dblAry) like I explained with char[][] .....
int CharPointerLength(char* ptr) it is new function for char*. Don't need to worry about complication/problem! It works like in char[].
Example:

C#
string str_1 = "Hello World!";
char* charPtr_1 = StringToCharPointer(str_1);
Console.WriteLine($"Result: Importing string from char {CharPointerToString(charPtr_1)}");
Console.WriteLine($"Length of char*: {CharPointerLength(charPtr_1)}");

Result:

Result: Importing string from char Hello World!
Length of char*: 12

int CharDoublePointerLength(char** dblPtr) is not normal length, just is array length like char[][].
Please do not forget for string[] to char** has problem because I have tried to fix. It seems wrong cause string[] doesn't have correct array size like 4 = size of array but it need to fix:
[ HELLO ][ HELLO ][ HELLO ]/[ HELLO ] <- It means wrong length.
That is why we need to resolve if you add string.Empty or null as last length then it will able working fine. Example:

C#
string[] strings = { "Haha ", "Hehe ", "Hihi ", "Hoho ", "Huhu", string.Empty }; // <- Fix if you don't see last item of array.
char** charDblPtr_1 = StringArrayToCharDoublePointer(strings);
for(int i = 0; i < strings.Length - 1; i++) // Need to -1
{
    charDblPtr_1[i] = StringToCharPointer(strings[i]);
    Console.WriteLine($"{strings[i]}");
}
charDblPtr_1[strings.Length - 1] = null; // <- Need fix null

int arrayLength = CharDoublePointerLength(charDblPtr_1);
Console.WriteLine($"Length of char**: {arrayLength} ");

Result:

Haha
Hehe
Hihi
Hoho
Huhu
Length of char**: 5

Please be careful if you use char*[] or char** to string[] is ok!
Example with CharPointerArrayToCharDoublePointer()

C#
char*[] charPtrArrays = new char*[]
{
    StringToCharPointer("Bill Gates"), // USA, Ex Microsoft boss
    StringToCharPointer("Jeff Bezos"), // USA Amazon boss
    StringToCharPointer("Tim Cook"), // USA Apple boss
    StringToCharPointer("Thomas Mueller"), // Germany /[ mýler }/, soccer of Bayern Munich
    StringToCharPointer("Nils Petersen"), // Germany, ex soccer of SC Freiburg
    StringToCharPointer("Christian Streich"), // Germany, ex coacher of SC Freiburg
    StringToCharPointer("Juegen Klopp"), // Germany /[ jýken ]/, ex chacher of Liverpool FC
    StringToCharPointer("Olaf Scholz"), // Germany, prime minister of Germany
    StringToCharPointer("Angela Merkel"), // Germany, ex prime minister of Germany
    StringToCharPointer("Jericho Rosales"), // Philippines, player for television
};
char** charDblPtr_2 = CharPointerArrayToCharDoublePointer(charPtrArrays);
for (int i = 0; i < charPtrArrays.Length; i++)
{
    Console.WriteLine($"{i + 1} Name: {CharPointerToString(charDblPtr_2[i])}");
}

int arrayLength_2 = CharDoublePointerLength(charDblPtr_2);
Console.WriteLine("Array Length of char*[] {0} ", arrayLength_2); 

Result:

1 Name: Bill Gates
2 Name: Jeff Bezos
3 Name: Tim Cook
4 Name: Thomas Mueller
5 Name: Nils Petersen
6 Name: Christian Streich
7 Name: Juegen Klopp
8 Name: Olaf Scholz
9 Name: Angela Merkel
10 Name: Jericho Rosales
Array Length of char*[] 10 

And other example with CharDoubleArrayToCharPointerArray()

C#
char[][] charArrayArray = new char[][]
{
    new char[] { 'H', 'e', 'l', 'l', 'o' },
    new char[] { 'W', 'o', 'r', 'l', 'd' },
    StringToCharArray("and"),
    StringToCharArray("Mars's World")
};

char*[] chardblArray = CharDoubleArrayToCharPointerArray(charArrayArray);
foreach (var charAry in charArrayArray)
{
    Console.WriteLine($"CharArray: {CharArrayToString(charAry)}");
}

char[][] chardblArray_2 = CharPointerArrayToCharDoubleArray(chardblArray);
for (int i = 0; i < chardblArray_2.Length;i++)
{
    Console.WriteLine($"{i + 1} CharArray: {CharArrayToString(chardblArray_2[i])}");
}

int array_length = CharDoublePointerLength( // <- Length of char double pointer
                        CharPointerArrayToCharDoublePointer( // <- trying char** from char*[]
                            CharDoubleArrayToCharPointerArray(chardblArray_2) // <- trying char*[] from char[][]
                        )
                    );
Console.WriteLine($"Array Length of char[][] is {array_length}"); 

Result:

CharArray: Hello
CharArray: World
CharArray: and
CharArray: Mars's World
1 CharArray: Hello
2 CharArray: World
3 CharArray: and
4 CharArray: Mars's World
Array Length of char[][] is 4 

That is all with char[], char*, char**, char*[] and char[][] and more ...
If you are excited to use with TerraFX.Interop.Windows then you will enjoy your new functions with charX/charXX and length of char* and char** and enjoy your development....


sbyte* <-> string and string <-> sbyte*

Example for SDL2 Wrapper (DeafMan1983.Interop.SDL2):

For string to sbyte* and sbyte* from string):

C#
// Example for title in SDL_CreateWindow()
sbyte* title = SBytePointerFromString("HelloSDL");
...
SDL_Window* window = SDL_CreateWindow(title, ... );

Or sbyte* to string (string from sbyte*).

C#
// Example for printf()

[DllImport("c")]
private static extern int printf(sbyte* fmt);
public static int Printf(sbyte* fmt, params object[] args)
{
    string result = StringFromSBytePointer(fmt);
    if (result == null)
        return 1;
    return printf(SBytePointerFromString(string.Format(result, args));
}

Two nice ways for sbyte* and string, you can use like this.

And nice example with Gtk3/Gtk4:

string[] to sbyte** (sbyte** from string[])

C#
static int Main(string[] args)
{
    GtkApplication* app = gtk_application_new(SBytePointerFromString("org.gtk.example"), 
                          GApplicationFlags.G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, ACTIVATE, G_CALLBACK
                    ((delegate* <gtkapplication*, void*, void>)&Activate), null);

    int argc = args.Length;
    sbyte** argv = SByteDoublePointersFromStringArray(args);
    int status = g_application_run(G_APPLICATION(app), argc, argv);

    g_object_unref(app);
    return status;
}

That is tricky and you can develop with C/C++ like main function with int and char* or char*[], etc. into C#.

sbyte** to string[] (string[] from sbyte**)

No code available. You know it just works like arguments/parameters from shared library example: Half-Life Sharp (still work in process).

Points of Interest

I find it very funny because ClangSharpPInvokeGenerator made const char* or char** into sbyte* or sbyte** because C/C++ <-> C# are not the same but for WinAPI is very sensitive because WinAPI doesn't support for sbyte* / sbyte** just uses char* / char** like in C/C++.

I expect that wchat* and  TChat* are not same to normal chat* because wchat means Windows-Charecter and has only 2 bytes.

Image 1

Since it is sensitive, I need to fix for UTF8 or ANSI format in char*/char**.

UPDATE: char* to string, string to char* and length of char* released

WARNING: Package will move to "DeafMan198.Utilities"

UtilitiesForUTF16 -> char* to string, string to char* and length of char* ( char** to string[] and string[] to char** and more will come see in Using in code )
UtilitiesForSByte -> sbyte* to string and string to sbyte* ( length of sbyte comes soon )
UtilitiesForByte -> byte* to string and string to byte* ( length of byte comes soon )

I have reworked hard with char* (UTF16) to string (UTF8)

Example: For WinAPI ( TerraFX.Interop.Windows )Image 2

Image 3

How do I get successful with WinAPI under C#.

Example:

C#
...
    static string DesktopAppStr = "DesktopApp";
    static string TitleStr = "Windows Desktop Guided Tour Application";

...

        HWND hWnd = CreateWindowEx(
            WS_EX_OVERLAPPEDWINDOW,
            StringToCharPointer(DesktopAppStr),
            StringToCharPointer(TitleStr),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, CW_USEDEFAULT,
            500, 100,
            HWND.NULL,
            HMENU.NULL,
            hInstance,
            null
        );

... 

That is all for WinAPI. I am very excited to see if Chinese Language won't show up. Yay!

Enjoy your reading if I release package for char* and string and length of char*.

For byte* <-> string:

C#
byte* StringToBytePointer(string input)
string BytePointerToString(byte* ptr)
int BytePointerLength(byte* ptr)
byte** StringArrayToByteDoublePointer(string[] input)
string[] ByteDoublePointerToStringArray(byte** ptrArray)
Int ByteDoublePointerLength(byte** ptrArray)

sbyte** <-> string:

C#
sbyte* StringToSBytePointer(string input)
string SBytePointerToString(sbyte* ptr)
int SBytePointerLength(sbyte* ptr)
sbyte** StringArrayToSByteDoublePointer(string[] input)
string[] SByteDoublePointerToStringArray(sbyte** ptrArray)
Int SByteDoublePointerLength(sbyte** ptrArray)

char* <-> string:

C#
char* StringToCharPointer(string input)
string CharPointerToString(char* ptr)
int CharPointerLength(char* ptr)
char** StringArrayToCharDoublePointer(string[] input)
string[] CharDoublePointerToStringArray(char** ptrArray) 
Int CharDoublePointerLength(char** ptrArray)

History

I started with SDL2-CS by Ethan Lee. But his SDL2-CS cannot use NativeAot. That is why I reworked into DeafMan1983.Interop.SDL2 with full pointers like in C/C++ because it works fine for NativeAot support. And new version comes with char* and more new features. It works as well with TerraFX.Interop.Windows.  

Add missed explanation about functions.

If you would like to spend me because I have a lot of works with trying fixes with string[] and char** that's way. See information !

Sorry no PayPal/Skrill:
Only TRX, MATIC or LTC under crypto wallet cause I have to earn more money.
Please notify me! Okay!

Nuget Gallery

It will come soon. ( I am working currently. Sorry for hesitation! )

Check out Nuget Package

dotnet add package DeafMan1983.Utilities

It uses sbyte*<->string ,sbyte**<->string[], and new char´*<->string and more new ...

If you want to check my Nuget packages, you can visit my packages.

Have fun and happy coding!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)