Czy można uzyskać char*
dla zmiennej string
w języku C#?char * wskaźnik ze stringa w C#
muszę przekonwertować ciąg ścieżki do char*
do korzystania z niektórych funkcji natywnej win32 ...
Czy można uzyskać char*
dla zmiennej string
w języku C#?char * wskaźnik ze stringa w C#
muszę przekonwertować ciąg ścieżki do char*
do korzystania z niektórych funkcji natywnej win32 ...
Możesz przekazać StringBuilder
jako char*
.
Spójrz na http://pinvoke.net, aby sprawdzić, czy podpis funkcji nie jest już dostępny.
można uzyskać byte [] tablicy z łańcucha przy użyciu Encoding.ASCII.GetBytes. Jest to prawdopodobnie zamienny na char * za pomocą instrukcji fixed w języku C#. (Przypina przydzieloną pamięć, nie pozwalając gc jej przenieść - wtedy możesz zrobić wskaźnik do niej).
Tak więc moja odpowiedź brzmi "tak" tylko wtedy, gdy uda się przekonwertować bajt * na char *. (w C/C++ to nie byłby problem, ale nie jestem pewien co do C#)
PS> Wyślę trochę kodu później, jeśli znajdę zakładkę do artykułu na ten temat. Wiem, że mam to gdzieś ..
należy również rozważyć Encoding.UTF8 jak zachowa wszystkie znaki unicode. – asveikau
A raczej lepiej jest użyć Encoding.Unicode (i PWSTR na końcu C), jeśli przechodzisz do natywnej funkcji Win32 ... – asveikau
Musisz najpierw sprawdzić, czy nie są one wielobajtowe (i myślę, że w rzeczywistości są), ponieważ komplikuje to "trochę" ... – kubal5003
To zależy od tego, co chcesz zrobić. Kiedy wywołasz funkcję Win32 przez PInvoke, powinieneś być w stanie po prostu przekazać zmienną String; struktura organizuje wszystko dla ciebie. Jeśli potrzebujesz czegoś bardziej skomplikowanego, spójrz na Marshal.StringToHGlobalAnsi i inne metody z klasy Marshal
.
Aby połączyć 2 ankiety już podane, zależy to od kierunku, w jakim potrzebujesz dla danego parametru.
Jeśli funkcja wymaga tylko ciągu wejściowego, tj. const char *
, można użyć argumentu typu System.String
(lub zwykłego string
).
Jeśli funkcja wypełnia ciąg, tj. char * buffer, int bufferSize
, można przekazać System.Text.StringBuilder
.
W obu przypadkach (auto-) Marshaling wykona dla Ciebie niezbędne konwersje.
Dziękuję już za spostrzeżenia, ale mam kilka dodatkowych uwag w komentarzach do wpisu poniżej ... – Kris
Dziękuję za wyjaśnienie różnicy między funkcją, która po prostu bierze ciąg, i taką, która buduje ciąg. Wszyscy po prostu zachwalali "StringBuilder", ale nie wydawało się to właściwe, jeśli funkcja nie będzie modyfikować napisu. – mpen
Cóż można na pewno to zrobić:
string str = "my string";
unsafe
{
fixed (char* p = str)
{
// do some work
}
}
gdzie jest operatorem (char *) związanych z przedmiotem strun. Format wyjściowy może jednak nie być zgodny z podstawowym formatem C lub innym ... jest to jednak całkiem dobre rozwiązanie do analizy ciągu znaków. Mam nadzieję, że jest to pomocne dla każdego, kto przeczyta ten post.
Daje to wskaźnik do elementów "System.Char", który odpowiada plikowi WCHAR * 'Win32, ale pytanie wymaga' char * '. –
Nie niebezpieczny kontekst wymagana jest następujący fragment kodu (i tak to pokazuje wewnętrzne śruby i bity o realizacji string
„GetHashCode
metoda pokazuje, że to różnica z jednym w Javie, ponieważ w C# wartość hashcode ISN” t buforowane i ogólnie to pokazuje, że C# struny nie są ostatecznie niezmienne jak ty może nauczono, nie może uporać się z Fon Neiman):
using System;
using System.Runtime.InteropServices;
namespace Guess
{
class Program
{
static void Main(string[] args)
{
const string str = "ABC";
Console.WriteLine(str);
Console.WriteLine(str.GetHashCode());
var handle = GCHandle.Alloc(str, GCHandleType.Pinned);
try
{
Marshal.WriteInt16(handle.AddrOfPinnedObject(), 4, 'Z');
Console.WriteLine(str);
Console.WriteLine(str.GetHashCode());
}
finally
{
handle.Free();
}
}
}
}
To jest niepoprawne, zobacz http://stackoverflow.com/a/10980174/3427520 – zwcloud
@zwcloud ** Jest całkowicie niewłaściwa do stwierdzenia, odpowiedź jest poprawna i najbardziej wydajna i najmniej uparty (w odniesieniu do niebezpiecznego kontekstu) * *. Odpowiedź spełnia dokładnie to, o co została poproszona. Przypisanie wskaźnika ciągu do 'GCHandle.alloc' nie spowoduje żadnych wycieków pamięci, chyba że narzucimy niewłaściwe użycie wskaźników w późniejszym kontekście. Cała koncepcja wskaźnika/pamięci w języku C# jest uważana za temat niskiego poziomu/zaawansowany, a jeśli idziesz za pomocą wskaźników, oznacza to, że rozumiesz całą koncepcję i zasadniczo wiesz, co robisz. – Lu4
W odniesieniu do zadanego pytania i odpowiedzi, punkt jest całkowicie poprawny, ale nie ma nic wspólnego z powyższym pytaniem, nie wspomniano, że ktokolwiek będzie przechowywać wskaźnik. Jeśli miałbyś przechowywać do późniejszego wykorzystania napis utworzony w języku C#, to oczywiście musiałbyś go skopiować w C, ponieważ wiązałby się z przydzieleniem tego ciągu w C, co pozwoliłoby C na późniejsze przydzielenie go. Oznacza to, że po prostu nie można przypiąć wskaźnika do końca życia ani dobrze jest marnować (tworzyć) kopię napisu w języku C# i przechowywać go w C, ponieważ C nie będzie w stanie zwolnić go później. – Lu4
+1, Lub po prostu 'ciąg', jeśli jest to parametr wejściowy. – user7116
Udzielam tej odpowiedzi, ponieważ zasadniczo odpowiedziałeś na moje pytanie, ale wydaje mi się, że przynajmniej dla tego, co robiłem, naprawiono (char * s = string) {...} – Kris
Próbowałem tego z SecureStringiem (char *, int length) i ani SecureString (sb, sb.Length) ani SecureString ((char *) sb, sb.Length) działa. Says nie może konwertować System.Text.StringBuilder na char *. – Despertar