C # llamando a C DLL, pasa char * como parámetro incorrecto

Estoy llamando a una DLL (C escribe) en lenguaje C # en VS2012. mylib.dll es el dll nativo que voy a llamar en C #, y mylib.dll también llamará a otro mylib_another.dll también.

Declaración de función C como:

extern DECLSPEC_DLL BOOLEAN_TYPE SetConnection(char *dev, char *addr); 

En mi archivo C #, lo declaro como:

 [DllImport("C:\\mylib.dll", EntryPoint = "SetConnection", CharSet = CharSet.Auto)] public static unsafe extern int SetConnection(StringBuilder dev, StringBuilder addr); 

Cuando lo llamé en código, encontré que la cadena solo pasaba un carácter, cuando paso dev como “USB”, la DLL nativa solo obtiene una “U” en realidad.

Si cambio de statement a:

 [DllImport("C:\\mylib.dll", EntryPoint = "SetConnection", CharSet = CharSet.Ansi)] public static unsafe extern int SetConnection(StringBuilder dev, StringBuilder addr); 

A continuación, se generará una excepción de excepción de System.AccessViolationException:

 System.Reflection.TargetInvocationException was unhandled HResult=-2146232828 Message=Exception has been thrown by the target of an invocation. Source=mscorlib StackTrace: at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams) at QC.QTMDotNetKernel.DotNetKernel.RunDotNetTest(Object stateObject) at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() InnerException: System.AccessViolationException HResult=-2147467261 Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 

¿Alguna idea sobre eso?

Se resolvió de la siguiente manera (la respuesta es para la primera pregunta, para la segunda, es decir, porque mylib.dll llamó a otra DLL nativa y el sistema no la encontró).

Un problema similar aquí:

Cuando solo recibe un carácter como ese, normalmente significa que está pasando una cadena Unicode (UTF16) a una función C / C ++ que espera un formato de 8 bits como ASCII, UTF8 o ANSI.

El formato Unicode de 16 bits termina con un byte de sus dos bytes establecidos en cero para los caracteres en el rango ASCII / ANSI, y debido a que un progtwig C / C ++ trata un byte cero como un carácter de final de cadena, trunca la cuerda.

Es fácil intentar usar ANSI para ver si ayuda; cambio

 CharSet = CharSet.Auto 

a

 CharSet = CharSet.Ansi 

Hay algunas cosas mal con tu p / invocar:

  1. La convención de llamada parece ser cdecl . No se especifica en el código nativo y el valor predeterminado más probable es cdecl .
  2. Usted está pasando StringBuilder que se utiliza para out parámetros de out . Tenga en cuenta que estoy asumiendo que los dos parámetros son ambos parámetros de entrada.
  3. El conjunto de caracteres es incorrecto. El código nativo recibe texto codificado de 8 bits.
  4. No es necesario que esté utilizando unsafe .

Una statement corregida es:

 [DllImport(@"C:\mylib.dll", CallingConvention=CallingConvention.Cdecl)] public static extern int SetConnection(string dev, string addr); 

Puede omitir la especificación del conjunto de caracteres ya que ANSI es el valor predeterminado. Por supuesto, no se CharSet=CharSet.Ansi nada con especificar CharSet=CharSet.Ansi si prefiere ser explícito. No es necesario especificar EntryPoint si es el mismo nombre que la función que declara.