¿Es posible obtener char*
para una variable string
en C#?puntero char * de cadena en C#
Necesito convertir una cadena de ruta a un char*
para el uso de alguna función Win32 nativa ...
¿Es posible obtener char*
para una variable string
en C#?puntero char * de cadena en C#
Necesito convertir una cadena de ruta a un char*
para el uso de alguna función Win32 nativa ...
Puede pasar StringBuilder
como char*
.
Eche un vistazo a http://pinvoke.net para ver si la firma para la función no está ya allí.
Puede obtener byte [] matriz a partir de cadenas usando Encoding.ASCII.GetBytes. Esto es probablemente convertible en char * utilizando una instrucción fija en C#. (Esto fija la memoria asignada, no permitiendo que gc la mueva, entonces puede hacer un puntero a ella).
Así que mi respuesta es sí solo si logras convertir byte * a char *. (en C/C++ esto no sería un problema, pero no estoy seguro de C#)
PD> Publicaré algún código más adelante si encuentro un marcador en un artículo sobre esto. Sé que lo tengo en alguna parte ...
también debe considerar como Encoding.UTF8 que mantendrá todos los caracteres Unicode. – asveikau
O más bien, es mejor usar Encoding.Unicode (y PWSTR en el extremo C) si pasa a una función Win32 nativa ... – asveikau
Primero debe verificar si no son multibyte (y creo que de hecho son), porque esto lo complica un poco "... – kubal5003
Eso depende de lo que quieras hacer. Cuando llama a una función Win32 a través de PInvoke, debería poder pasar la variable String; el marco lo ordena todo para ti. Si necesita algo más complicado, eche un vistazo a Marshal.StringToHGlobalAnsi y otros métodos de la clase Marshal
.
Para combinar 2 elementos ya indicados, depende de la dirección que necesite para su parámetro.
Si la función solo necesita una cadena de entrada, es decir, const char *
, puede usar un argumento del tipo System.String
(o simple string
).
Si la función rellena una cadena, es decir, char * buffer, int bufferSize
, puede pasar un System.Text.StringBuilder
.
En ambos casos, el (auto) Marshaling hará las conversiones necesarias para usted.
Gracias por las estadísticas, pero tengo algunos comentarios adicionales en los comentarios de una publicación a continuación ... – Kris
Gracias por explicar la diferencia entre una función que solo toma una cadena y una que crea una cadena. Todos siguieron promocionando 'StringBuilder' pero eso no parecía correcto si la función no iba a modificar la cadena. – mpen
Bueno ciertamente se podría hacer esto:
string str = "my string";
unsafe
{
fixed (char* p = str)
{
// do some work
}
}
donde hay un operador (char *) unido al objeto de cadena. Sin embargo, el formato de salida puede no ser compatible con el C subyacente u otro formato ... esta es, sin embargo, una buena solución para analizar la cadena. Espero que sea útil para cualquiera que lea esta publicación.
Esto da un puntero a los elementos 'System.Char', que corresponde a' WCHAR * 'de Win32, pero la pregunta pide' char * '. –
No se requiere contexto inseguro para la siguiente pieza de código (y sí que muestra los pernos internos y bits acerca de la aplicación de string
'GetHashCode
método s muestra que es diferencia con uno en Java porque en C# el valor de ISN código hash' t en caché y, en general muestra que C# cadenas no son inmutables en última instancia, al igual que es posible que haya sido enseñado, no pueden hacer frente a 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();
}
}
}
}
Esto es incorrecto, vea http://stackoverflow.com/a/10980174/3427520 – zwcloud
@zwcloud ** Es totalmente incorrecto decirlo, la respuesta es correcta y la más eficiente y menos obstinada (en relación con el contexto inseguro) * *. La respuesta hace exactamente lo que se le pidió que hiciera. Fijar el puntero de cadena a través de 'GCHandle.alloc' no hará que la memoria pierda a menos que imponga un uso incorrecto de los punteros más adelante en un contexto subyacente. Todo el concepto de puntero/memoria en C# se considera de bajo nivel/tema avanzado y, si utiliza punteros, significa que comprende todo el concepto y básicamente sabe lo que está haciendo. – Lu4
En relación con las preguntas y respuestas a las que se hace referencia, el punto es totalmente válido pero no tiene nada que ver con la pregunta anterior, no se mencionó que alguien almacenará el puntero. Si tuviera que almacenar para usar más adelante una cadena creada en C#, obviamente necesitaría copiarla en C porque implicaría la asignación de esa cadena en C, lo que permitiría que C lo elimine posteriormente. Por lo general, significa que no puede anclar su puntero de por vida ni es bueno ordenar (crear) una copia de su cadena en C# y almacenarla en C porque C no podrá desasignarlo más tarde. – Lu4
+1, o simplemente 'cadena' si es un parámetro de entrada solamente. – user7116
Estoy otorgando esta respuesta ya que básicamente respondió mi pregunta, pero parece que, al menos por lo que estaba haciendo, todo lo que se necesitaba era arreglado (char * s = cadena) {...} – Kris
Probé esto con SecureString (char *, int length) y tampoco funciona SecureString (sb, sb.Length) o SecureString ((char *) sb, sb.Length). Dice que no puede convertir System.Text.StringBuilder en char *. – Despertar