DllImport.net frameworksdk documentation -> reference -> Compiler and Language Reference -> C# -> C# programmer's Reference -> C# tutorials -> platform invoke tutorials

解决方案 »

  1.   

    那要看是什么DLL,是WIN32 DLL还是COM DLL呢
    具体请看C# interop的解析。是关于如何工作于
    unsafe code
      

  2.   

    好象只要user了库就可以直接用了。
      

  3.   

    看清楚了!返回和参数可是CString啊!
    我还真不知道C#怎么Marshal CString呢:),要真像这样做还得费不少功夫呢!
    我的建议是:先用VC++做一层包装。这个Wrap的工作就是把CString的参数和返回值转换成标准的const char*。然后把这个Wrap也编译成Dll,从C#中直接用这个Wrap的DLL。这样要容易得多。
      

  4.   

    =====>>> qqchen79(知秋一叶):
    谢谢。
    我也有这种想法。
    不过,不知可不可以直接在C#进行调用?
    我试了一下,好像直接在c#中使用string就可以了.
    关键是: int *怎么处理。
    它通过int *来传出函数的执行情况,并据此判断、处理?
    谢谢!!!
      

  5.   

    看了MFC的源码,原来CString里面就只有一个LPTSTR数据成员,而且没有virtual函数,所以其内存结构与LPTSTR完全一样,直接Marshal成LPTSTR也能工作——虽然感觉上不太好。int*,有几种办法,最简单的使用ref/out就应该可以:
    string FunSys(ref int a, string b);
    string FunSys(out int a, string b); //急得调用的时候也要加ref/out其次,用unsafe code,是可以取得int*的,所以可以直接用int*声明。
    最后,Marshal.HGlobalAlloc可以在GlobalHeap中申请内存,返回IntPtr,相当于int*,所以也可以这样写:
    string FunSys(IntPtr pa, string b); //用完记得释放。
      

  6.   

    我的代码是这样写的,执行的时候总是报错。
    请指教,谢谢!
    ------------
    An unhandled exception of type 'System.NullReferenceException' occurred in CallAPI2.exe
    Additional information: Object reference not set to an instance of an object.
    ------------
    源代码:
    private void button1_Click(object sender, System.EventArgs e)
    {
       string a="aaa";
       string strResult="";
       int i=0;
       strResult = FunSys(ref i, a);
    }
    [DllImport("DllName.dll",CharSet=CharSet.Auto)]
    public static extern string FunSys(
       ref int para1,
       string para2
    );
      

  7.   

    果然是返回值的问题,CString作为参数Marshal成string没问题,但作为返回值的时候就有问题了。我试着把返回值类型改成const char*或者LPTSTR,调用就没问题了,这和int参数无关,ref和out都是可以的。
      

  8.   

    了解了,对于x86 native code而言(例如C++/C程序),返回值通常放在eax/edx寄存器当中,如果是C++中的对象,那么对象将会构件在heap中,对象的指针则放在eax中。而如果返回值是指针,如LPTSTR,那么这个指针的值直接放在eax中。这时候,返回LPTSTR和CString的堆栈结构就不同了。
     Cstring的情况:
        eax --> CString Object(LPSTR) ---> 实际字符串
     const char*/LPSTR的情况:
        eax --> 实际字符串
      

  9.   

    qqchen79(知秋一叶):那这个问题,怎么解决???
    谢谢!
      

  10.   

    其实我觉得最好还是用一层包装的方法,直接使用MFC中的类终究不是好事。
    但如果你执意要用CString的话,可以试试这样:CString在C#中的定义是:
    [StructLayout(LayoutKind.Sequential)]
    public struct CSString {
        [MarshalAs(UnmanagedType.LPTStr)]
        string _str;
    }
    可以把函数的返回这说明成为CSString的形式:
    public static extern CSString FunSys( 
    ref int para1, 
    string para2 
    );
    也许可以。
      

  11.   

    qqchen79(知秋一叶): 
    按照你提供的方法,出现如下错误信息:
    An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in CallAPI2.exeAdditional information: Method's type signature is not PInvoke compatible.
    --------------
    谢谢。
      

  12.   

    算了,I give up. :(
    还是加一层包装吧。
      

  13.   

    qqchen79(知秋一叶): 
    请问如何在vc6.0中添加一层包装。
    现在只提供了DLL和lib文件。
    谢谢!
    谢谢各位高手!
      

  14.   

    try below code:
    写在你的调用函数前[System.Runtime.InteropServices.DllImportAttribute("filename.dll")]
    public static extern CString FunSys(int * par1, CString par2);
      

  15.   

    不对吧!
    C#中并没有CString类呀!!!
    还是说 怎样在VC6.0中如何调用吧!
    谢谢
      

  16.   

    就是做一个自己的DLL,调用前面说的那个DLL里的函数。
    #include <TCHAR.H>void FunSysWrap(int* p, LPTSTR pstr, LPTSTR buffer) {
      CString s(pstr);
      CString ret = FunSys(p, s);
      LPTSTR temp = ret.LockBuffer();
      _tcscpy(buffer, temp);
      return;
    } 然后C#里面调用FunSysWrap(ref int, string, StringBuilder)就可以了。至于怎么用VC生成DLL,参考MSDN的例子吧,记得把.lib包含到Project的link里面就可以了。
      

  17.   

    sorry,忘了UnlockBuffer,:) MFC我也不是很熟的说。
      

  18.   

    Ok, I finally got this damn thing work! :)
    下面是整个代码,很难解释,就将就着用把:
    DLL:
    CString FunSys(int* p, CString str);C#:
    [StructLayout(LayoutKind.Sequential)] 
    public struct MyString { 
    public IntPtr _str; 
    } [DllImport("mydll.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
    public extern static void DllFun(IntPtr pt, ref int i, string str);
    //千万别问我为什么:)调用:
    int i = 0;
    IntPtr mem = Marshal.AllocHGlobal(64); //申请多点内存,先。
    DllFun(mem, ref i, "hello, world");
    MyString mystr = (MyString)Marshal.PtrToStructure(mem, typeof(MyString));
    string str = Marshal.PtrToStringAnsi(mystr._str);
    Console.WriteLine(str);
    Marshal.FreeHGlobal(mem);
    ...真是麻烦,乖乖妹要请客的说!:)