【问题标题】:system.access.violation exception while calling c++ function from a thread in c#从 c# 中的线程调用 c++ 函数时出现 system.access.violation 异常
【发布时间】:2015-02-04 20:03:53
【问题描述】:

我正在将 c++ 函数从 dll 导入我的 winform c# 应用程序:

[DllImport(@"eyeWhere.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
public static extern int Eye_GetPositionS(string filename, [MarshalAs(UnmanagedType.LPArray, SizeConst = 9)] double[] sensors);

当我从构造函数调用函数时,它工作正常。

问题是当我从
中打开的新线程调用它时 “斑点 websocket 服务器”Fleck,“onMessage”操作,
然后它抛出“system.access.violation”异常。

我设法将问题缩小到我正在传递的双数组, 似乎指向它的指针已损坏。

我找不到问题的根源,一件事是确定 dll 中的函数在我测试时工作正常。

函数调用(两个阶段):

  1. 在“fleck”中打开新线程:

socket.OnMessage = message => {Thread locationThread = new Thread( unused => processLocation(fileName,socket,sensorsList,sensors) ); locationThread.Start();}

  1. 实际功能:

private void processLocation(string fileName, IWebSocketConnection sock, List<Sensor> sensorsList, double[] sensors) { int map_position = Eye_GetPositionS(fileName,sensors);
string locationString = "floor:1,mx:" + (map_position / 10000) + ",my:" + (map_position % 10000); // send location string to user sock.Send(LOCATION_CODE + "-" + locationString);}

界面是:

extern "C" __declspec(dllexport) int Eye_GetPositionS(const wchar_t *fname_mob, double sensors[9], int &amp;map_x, int &amp;map_y)

我没有像编写 dll 的人所同意的那样传递最后两个参数 (int&)。

【问题讨论】:

  • 显示你如何调用函数。
  • 也许你不能从主线程以外的线程调用函数。您应该通过编写一些 C++ 代码来解决这个问题,以确保 p/invoke 没有混淆。我的意思是,如果 p/invoke 是错误的,你怎么能指望我们提供帮助?你只显示了界面的一半。
  • 问题是我无法访问 dll 中的代码,这是我为一家初创公司做的项目的一部分。我可以说我在同一个 dll 中使用了类似的函数,并且在相同的工作流程下运行良好。
  • 不知道接口的还不如放弃。或者你的意思是你没有实现。如果你有接口,我们看不到吗?
  • 我添加了接口,你说得对,我没有实现。

标签: c# c++ multithreading exception dllimport


【解决方案1】:

我没有按照与编写 DLL 的人的约定传递最后两个参数 (int&amp;)。

嗯,问题来了。您不能省略参数。应该是:

[DllImport(@"eyeWhere.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Unicode)]
public static extern int Eye_GetPositionS(
    string filename, 
    [In, MarshalAs(UnmanagedType.LPArray, SizeConst = 9)] 
    double[] sensors,
    ref int map_x,
    ref int map_y
);

无论编写 DLL 的人怎么说,您都不能省略这些参数。也许他的意思是参数真的是int*,你可以传nullptr

我已经为这些参数使用了ref,但也许它们应该是out。你大概知道哪个是合适的。

同样,我猜测sensors 参数的意图。如果数据流出而不是流入,则使用Out。如果数据双向流动,请使用[In, Out, ...]

【讨论】:

  • 您确定在“MarshalAs”之前应该将“Out”替换为“In”吗?
  • 我不知道。这是你需要回答的问题!数据流向哪种方式?
  • 好的,很抱歉,它的“In”传感器被传递到函数中。如何将一个空指针传递给最后一个整数地址?
  • 你不能将 null 传递给 C++ 引用
  • 如果它是 int* 而不是 int& 那么您可以将参数声明为 IntPtr 并传递 IntPtr.Zero。虽然我感到困惑。也许在 dll 开发者方面。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 2012-05-29
相关资源
最近更新 更多