Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#调用C DLL,将char*作为参数传递不正确_C#_Dll_Pinvoke_Native - Fatal编程技术网

C#调用C DLL,将char*作为参数传递不正确

C#调用C DLL,将char*作为参数传递不正确,c#,dll,pinvoke,native,C#,Dll,Pinvoke,Native,我正在VS2012中用C语言调用DLL(C写)。mylib.dll是我将在C#中调用的本机dll,mylib.dll也将调用另一个mylib#u另一个.dll C功能声明如下: extern DECLSPEC_DLL BOOLEAN_TYPE SetConnection(char *dev, char *addr); 在我的C#  文件,我声明为: [DllImport("C:\\mylib.dll", EntryPoint = "SetConnection", CharSet = Char

我正在VS2012中用C语言调用DLL(C写)。mylib.dll是我将在C#中调用的本机dll,mylib.dll也将调用另一个mylib#u另一个.dll

C功能声明如下:

extern DECLSPEC_DLL BOOLEAN_TYPE SetConnection(char *dev, char *addr); 
在我的C#  文件,我声明为:

[DllImport("C:\\mylib.dll", EntryPoint = "SetConnection", CharSet = CharSet.Auto)]
public static unsafe extern int SetConnection(StringBuilder  dev,  StringBuilder addr);
当我在代码中调用它时,我发现字符串只传递了一个字符,当我将dev作为“USB”传递时,本机DLL实际上只得到一个“U”

如果我将声明更改为:

[DllImport("C:\\mylib.dll", EntryPoint = "SetConnection", CharSet = CharSet.Ansi)]
public static unsafe extern int SetConnection(StringBuilder  dev,  StringBuilder addr);
然后它将引发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.
有什么想法吗

已解决如下问题(第一个问题的答案是,第二个问题的答案是,这是因为mylib.dll调用了另一个本机dll,而系统没有找到它)


类似的问题

当您只收到一个这样的字符时,通常意味着您将Unicode(UTF16)字符串传递给C/C++函数,该函数需要8位格式,如ASCII、UTF8或ANSI

对于ASCII/ANSI范围内的字符,16位Unicode格式最终将其两个字节中的一个字节设置为零,并且由于C/C++程序将零字节视为字符串结尾字符,因此会截断字符串

很容易尝试使用ANSI,看看它是否有帮助;改变

CharSet = CharSet.Auto


您的p/invoke有一些问题:

  • 调用约定看起来是
    cdecl
    。本机代码中没有指定它,最有可能的默认值是
    cdecl
  • 您正在传递用于输出参数的
    StringBuilder
    。注意,我假设这两个参数都是输入参数
  • 字符集错误。本机代码接收8位编码文本
  • 您不需要使用不安全的
  • 更正声明如下:

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

    您可以省略字符集的规范,因为ANSI是默认值。当然,如果您喜欢显式的话,那么指定
    CharSet=CharSet.Ansi
    并没有什么坏处。如果入口点与您声明的函数名称相同,则无需指定。

    对于
    SetConnection()
    的这两个声明是相同的。它们应该不同吗?CharSet.Auto是错误的,让它成为Ansi。StringBuilder对于以“Set”开头的函数很可能是错误的,将其设置为字符串。第二个是:
    CharSet=CharSet.Ansi
    当更改为此时,它会引发System.AccessViolationException。第二个是:
    CharSet=CharSet.Ansi
    当更改为此时,它会引发System.AccessViolationException.Yeah,这一个是正确的,关于
    系统的第二个问题。AccessViolationException
    是因为在本机dll中,是的,这一个是正确的,关于
    系统的第二个问题。AccessViolationException
    是因为在本机dll中,我调用了另一个本地dll,称为mylib_other.dll,因为我是从完整路径加载mylib.dll的,所以主程序无法自动加载此路径中的mylib_other.dll。因此,所有这些dll(代码中加载的dll除外)都应该放在主程序的主目录中,以确保它可以自动加载。我确实需要这一行:
    CharSet=CharSet.Ansi
    来解决第一个问题。不,您不需要。它是默认值,可以省略。显然,您不能像在问题中那样将其设置为
    CharSet.Auto
    ,但我的答案中的代码是准确的。
    [DllImport(@"C:\mylib.dll", CallingConvention=CallingConvention.Cdecl)]
    public static extern int SetConnection(string dev, string addr);