Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/110.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++;来自C代码的函数?_C#_C++_Marshalling_Dllimport_Access Violation - Fatal编程技术网

C# 为什么在调用导入的C++;来自C代码的函数?

C# 为什么在调用导入的C++;来自C代码的函数?,c#,c++,marshalling,dllimport,access-violation,C#,C++,Marshalling,Dllimport,Access Violation,我已经读了很多关于这个话题的文章,但是我还没有找到解决问题的方法 从我的C代码中,我尝试用 dLimPurt调用C++函数。不幸的是,我没有C++代码,但是头文件给出了函数的信息: ABCD Initialize ( IN FLOAT a , IN DWORD b ); ABCD也在头文件中定义: #define EFGH extern "C" ... #define ABCD EFGH __declspec(dllexport) HRESULT WINAPI 在C#代码

我已经读了很多关于这个话题的文章,但是我还没有找到解决问题的方法

<>从我的C代码中,我尝试用<代码> dLimPurt调用C++函数。不幸的是,我没有C++代码,但是头文件给出了函数的信息:

ABCD Initialize
(
  IN FLOAT a  
  , IN DWORD b  
);  
ABCD也在头文件中定义:

#define EFGH extern "C"
...
#define ABCD EFGH __declspec(dllexport) HRESULT WINAPI
在C#代码中,我尝试像这样调用Initialize函数:

[DllImport("path.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern UInt32 Initialize([In] float a, [In] UInt32 b);
...
Initialize(50.0f, 0);
根据需要,数据类型
float
不需要编组,我可以使用
UInt32
代替
DWORD
。对于返回类型,
HRESULT WINAPI
,我使用数据类型
UInt32
,据我所知,也不需要编组?(我还尝试对参数和返回值使用其他数据类型,但总是得到相同的异常)

对于DllImport属性,已经测试了
字符集
调用约定
的许多可能性,但没有成功。在声明函数时,我还尝试了两种变体,包括参数的
[In]
属性

调用函数时,会引发异常:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
我是不是遗漏了什么?成功调用函数的下一步是什么

多谢各位


这是完整的C代码。如上所述,我没有用于构建.dll文件的代码。此外,我不允许共享dll

using System;
using System.Runtime.InteropServices;

namespace MyNamespace
{
  class Program
  {
    [DllImport("path.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern UInt32 Initialize([In] float a, [In] UInt32 b);

    static void Main(string[] args)
    {
      Initialize(50.0f, 0); // <- throws System.AccessViolationException
      Console.ReadLine();
    }
  }
}
使用系统;
使用System.Runtime.InteropServices;
名称空间MyNamespace
{
班级计划
{
[dlliport(“path.dll”,CharSet=CharSet.Unicode,CallingConvention=CallingConvention.StdCall)]
公共静态外部UInt32初始化([In]浮点a,[In]UInt32 b);
静态void Main(字符串[]参数)
{

初始化(50.0f,0);//最后,我可以确定问题

为了检查参数的数据类型和返回值,我在dll上使用了反编译器Snowman。看起来dll只定义了接口,实现在另一个dll文件中,开发人员忘记了首先发送

一旦第二个.dll文件存储在我的程序的runtime文件夹中,函数调用就会工作。我还想指出的是,该调用可以使用
[in]
参数属性,也可以不使用
[in]
参数属性

虽然我不知道抛出异常的确切原因
AccessViolationException:试图读取或写入受保护内存…
(我认为另一个异常可能更适合这里),但我很高兴这个问题能够得到解决


感谢Ben Voigt和David Heffernan的评论!

如本文所述,该代码是正确的。我敢打赌,当您更改真实代码时,您转录了一些内容。请出示a。感谢您的评论!不幸的是,我不允许共享.dll文件,因此我无法提供可复制的示例。C#代码已接近完成,名称空间由一个类组成,该类的主函数只调用
Initialize(50.0f,0)当然,你可以分享一个可重复的例子。只要删掉任何敏感的东西。DavidHeffernan编辑了这个问题并添加了完整的C代码。不幸的是我没有用于构建C++ DLL的代码。而且,我不允许共享.dll文件或部分。标题文件的相关部分可以在问题中找到。遗憾的是,我不允许发布完整的.h文件。希望这有帮助。谢谢您的时间。@luk:我可以通过向您保证
[in]来为您节省一些组合供您试用这里不需要使用
。这是x86或x64代码还是其他体系结构?有些人比其他人更关心调用约定。
WINAPI
应该按照您的p/invoke已经指定的设置stdcall。