C#调用dll “尝试读取或写入受保护的内存。这通常指示其他内存已损坏"

fanhy125 2009-12-22 03:45:15
该DLL是将DICOM图片格式传到PIVIEW中。该程序在VC里已经实现,现要在C#里实现。dll里方法接口为BOOL __stdcall dicom_storescu_execute(LPCSTR servername, int serverport,
LPCSTR servertitle, LPCSTR clienttitle,
LPCSTR filelist, STORESCUCALLBACK callback);
其中STORESCUCALLBACK 是一个函数指针typedef void (__stdcall * STORESCUCALLBACK)(T_StoreProgress* progress);。
调用为:
isSuccessed = dicom_storescu_execute(TheadIPadress,
TheadServerPort ,
TheadServerTitle,
TheadClientTitle,
TheadImageFile ,
MyStoreScuCallback);
MyStoreScuCallback为一函数名
在C#中
public delegate void STORESCUCALLBACK(T_StoreProgress progress);
[DllImport("dcmtrans.dll", EntryPoint = "dicom_storescu_execute")]
public static extern bool dicom_storescu_execute(string servername,
int serverport, string servertitle, string clienttitle,
string filelist, STORESCUCALLBACK callback);
调用为

internal unsafe void startSCU(Object lpParam)
{
StoreSCUThead scu_CS = (StoreSCUThead)lpParam;
string TheadIPadress = scu_CS.strIPadress;
int TheadServerPort = scu_CS.strServerPort;
string TheadServerTitle = scu_CS.strServerTitle;
string TheadClientTitle = scu_CS.strClientTitle;
string TheadImageFile = scu_CS.strImageFile;
int mxh = scu_CS.Theadxh;
bool isSuccessed = false;
STORESCUCALLBACK callback = new STORESCUCALLBACK(MyStoreScuCallback);
isSuccessed = dicom_storescu_execute(TheadIPadress,
TheadServerPort,
TheadServerTitle,
TheadClientTitle,
TheadImageFile,
callback);

if (!isSuccessed)
falseNum++;
}

MyStoreScuCallback为函数名
public void MyStoreScuCallback(T_StoreProgress progress)
{
switch (progress.state)
{
case T_StoreProgressState.StoreBegin:
break;
case T_StoreProgressState.StoreProgressing:
break;
case T_StoreProgressState.StoreEnd:
break;
default:
break;
}
}
其中startSCU是开辟一个线程调用的
internal unsafe void OnSend(string path)
{
string m_aetitle="";
string m_ip = "";
int m_port = 0;
string m_Filename = "";
string m_path = "";
StringBuilder m_tmp = new StringBuilder(255);
m_Filename = path + "test.dcm";
m_path = path + "user_setting.ini";
GetPrivateProfileString("SetupDCM", "aetitle", null, m_tmp, 15, m_path);
m_aetitle = m_tmp.ToString();
GetPrivateProfileString("SetupDCM" , "ip" , null , m_tmp , 15 , m_path);
m_ip = m_tmp.ToString();
GetPrivateProfileString("SetupDCM", "port", null, m_tmp, 15, m_path);
m_port = Int32.Parse(m_tmp.ToString());
StoreSCUThead uStoreSCUThead = new StoreSCUThead();
uStoreSCUThead.strIPadress = m_ip;
uStoreSCUThead.strServerPort = m_port;
uStoreSCUThead.strServerTitle = "OPACS";
uStoreSCUThead.strClientTitle = m_aetitle;
uStoreSCUThead.strImageFile = m_Filename;
uStoreSCUThead.Theadxh = 1;
//Thread fThread = new Thread(new ThreadStart(startSCU));
Thread fThread = new Thread(startSCU);
fThread.Start(uStoreSCUThead);
fThread.Join(1000);
}
一编译就出错在调用函数dicom_storescu_execute“这报尝试读取或写入受保护的内存”的错。请问各位大哥,我是不是函数指针转化的类型出错啦?而且我把MyStoreScuCallback里参数换为不是指针类型的了。这些有影响吗?


...全文
303 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
KKND2006 2009-12-24
  • 打赏
  • 举报
回复
不同语言之间调用,最好是用COM,不然很容易出问题

那个DLL,实在不行,用COM再封装一次

我最近在折腾某市医保,他们提供了一个MFC DLL,结果用PB调用死活就是要报错,用VC调用就没问题,后面我干脆把医保DLL封装成COM,就天下太平了,COM这种规范还是很好用的
liaoyukun111 2009-12-24
  • 打赏
  • 举报
回复
是不是放错地方了?
wholesale3151 2009-12-24
  • 打赏
  • 举报
回复
isSuccessed = dicom_storescu_execute(TheadIPadress,
chinese wholesalers ,
TheadServerTitle,
TheadClientTitle,
TheadImageFile ,
MyStoreScuCallback);
wzuomin 2009-12-24
  • 打赏
  • 举报
回复
帮顶
fanhy125 2009-12-24
  • 打赏
  • 举报
回复
经过两天的仔细调试,我才发现我编的代码没有问题,MY GOD!
居然是PI VIEW服务器没开,怪不得我有时成功有时失败呢。不过经过这次我学了好多关于DLL调用的知识,感觉很充实。
最后我有一个发现:dicom_storescu_execute最后一个做回调使用的函数指针参数居然可以赋空,害的我到网上到处找在C#里定义函数指针和调用DLL里结构体的用法。。。。。
这个贴就到此为止了,感谢朋友们对我的帮助!!!!
shuli198869 2009-12-23
  • 打赏
  • 举报
回复
我出现这个错误是因为引用了临时的dll,没有引用bin目录下的
fanhy125 2009-12-23
  • 打赏
  • 举报
回复
我放在生成目录下
shuli198869 2009-12-23
  • 打赏
  • 举报
回复
说错了啊,不好意思,你引得dll是在bin文件夹下吗?是不是引成了obj文件夹下的临时的了
shuli198869 2009-12-23
  • 打赏
  • 举报
回复
我也遇到过这个问题,是你所调用的dll改变了,你重新看一下生成dll文档的类,再重新生成一下,再调用试试
fanhy125 2009-12-22
  • 打赏
  • 举报
回复
顶一个!!
我用unsafe模式下重新定义了
public delegate void STORESCUCALLBACK(T_StoreProgress *progress);

internal unsafe void MyStoreScuCallback(T_StoreProgress *progress)
{
switch (progress->state)
{
case T_StoreProgressState.StoreBegin:
break;
case T_StoreProgressState.StoreProgressing:
break;
case T_StoreProgressState.StoreEnd:
break;
default:
break;
}
}
发现能通过编译,但是执行结果isSuccessed 总是不成功的结果,也就是图片没发送出去。。。。
fanhy125 2009-12-22
  • 打赏
  • 举报
回复
额。。。。STORESCUCALLBACK是函数指针啊,用委托定义的传进去可以吗?
该方法是传参数进去,LPCSTR 转化为string应该是没问题的
xupeihuagudulei1 2009-12-22
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lovely_baby 的回复:]
如果参数是传进的话,用string是可以的,如果是传出的话,用StringBuilder。
  至于const  int*,用"ref  int"来替换。


int===> IntPtr
是不是类型错误了??
[/Quote]UP
又换头像了。
Lovely_baby 2009-12-22
  • 打赏
  • 举报
回复
如果参数是传进的话,用string是可以的,如果是传出的话,用StringBuilder。
至于const int*,用"ref int"来替换。


int===> IntPtr
是不是类型错误了??

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧