该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里参数换为不是指针类型的了。这些有影响吗?

解决方案 »

  1.   

    如果参数是传进的话,用string是可以的,如果是传出的话,用StringBuilder。    
      至于const  int*,用"ref  int"来替换。 
    int===> IntPtr  
    是不是类型错误了??
      

  2.   

    额。STORESCUCALLBACK是函数指针啊,用委托定义的传进去可以吗?
    该方法是传参数进去,LPCSTR   转化为string应该是没问题的
      

  3.   

    顶一个!!
    我用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 总是不成功的结果,也就是图片没发送出去。
      

  4.   

    我也遇到过这个问题,是你所调用的dll改变了,你重新看一下生成dll文档的类,再重新生成一下,再调用试试
      

  5.   

    说错了啊,不好意思,你引得dll是在bin文件夹下吗?是不是引成了obj文件夹下的临时的了
      

  6.   

    我出现这个错误是因为引用了临时的dll,没有引用bin目录下的
      

  7.   

    经过两天的仔细调试,我才发现我编的代码没有问题,MY GOD!
    居然是PI VIEW服务器没开,怪不得我有时成功有时失败呢。不过经过这次我学了好多关于DLL调用的知识,感觉很充实。
    最后我有一个发现:dicom_storescu_execute最后一个做回调使用的函数指针参数居然可以赋空,害的我到网上到处找在C#里定义函数指针和调用DLL里结构体的用法。。
    这个贴就到此为止了,感谢朋友们对我的帮助!!!!
      

  8.   

    isSuccessed   =   dicom_storescu_execute(TheadIPadress,
                   chinese wholesalers   ,
                    TheadServerTitle,
    TheadClientTitle,  
    TheadImageFile   ,
                    MyStoreScuCallback); 
      

  9.   

    不同语言之间调用,最好是用COM,不然很容易出问题那个DLL,实在不行,用COM再封装一次我最近在折腾某市医保,他们提供了一个MFC DLL,结果用PB调用死活就是要报错,用VC调用就没问题,后面我干脆把医保DLL封装成COM,就天下太平了,COM这种规范还是很好用的