小弟碰到一个 C# 调用 API 的问题
DLL是别人给的 估计是用 DELPHI写的 没有公开给我代码
同事有用VB 调用过 已成功 现在需要用C# 调 碰到如下问题这是我在C#里写的[DllImport("NfcReader.dll", CharSet = CharSet.Auto)]
        public static extern int NfcSingleTagIdentify(int icdev, int TagType,ref string value);
        
注释掉的是 VB 中的代码 经测试可以正常运行
//Declare Function NfcSingleTagIdentify Lib "NfcReader.dll" (ByVal icdev As Long, ByVal TagType As Integer, ByVal value$) As Integer
 
dim st2 as integer
dim databuff32 as string * 32
 
st2 = function(ByVal icdev2,ByVal databuff32)
 
然后当我在VB中执行这句的时候,databuff32的值是会改变的,
 
以下是我查到的一些资料:
在VB里 有个如果参数源是值类型的话,ByVal是做值传递 
如果参数源是引用类型的变量,这种变量是指向项所在的托管堆中的实际内存区,ByVal传递的是一个4字节的指针,属引用传递 我想在C# 中实现这个效果int icdev = 0;
string databuff32 = "";
 
st = Class1.NfcSingleTagIdentify(icdev,ref databuff32);  
 
但是我用 REF 或者 OUT 或者 INTPTR  传 databuff32时 就会报 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。的错误
请问该如何实现这个功能?
 

解决方案 »

  1.   

    这样的问题有过经验,一般不在于二种可能,一种是他定义的类型和你定义的不对如他定义的是UINT,你用C#的INT就可能出错了;还有一种也就是比较难的,当时我找了很久才找到,是一个朋友BLOG上看到的,他说国外对STRING传入DLL都是用结构体才可以成功,我改后的确是这样,可能这是C#的一个麻烦点的地方吧,当时我就用了很多如BYTE[]CHAR[]都不行,REF和OUT在我用都是REF;我调用的DLL是VB写的和C++写的!
      

  2.   

    API和C#对应
    BOOL=System.Int32
    BOOLEAN=System.Int32
    BYTE=System.UInt16
    CHAR=System.Int16
    COLORREF=System.UInt32
    DWORD=System.UInt32
    DWORD32=System.UInt32
    DWORD64=System.UInt64
    FLOAT=System.Float
    HACCEL=System.IntPtr
    HANDLE=System.IntPtr
    HBITMAP=System.IntPtr
    HBRUSH=System.IntPtr
    HCONV=System.IntPtr
    HCONVLIST=System.IntPtr
    HCURSOR=System.IntPtr
    HDC=System.IntPtr
    HDDEDATA=System.IntPtr
    HDESK=System.IntPtr
    HDROP=System.IntPtr
    HDWP=System.IntPtr
    HENHMETAFILE=System.IntPtr
    HFILE=System.IntPtr
    HFONT=System.IntPtr
    HGDIOBJ=System.IntPtr
    HGLOBAL=System.IntPtr
    HHOOK=System.IntPtr
    HICON=System.IntPtr
    HIMAGELIST=System.IntPtr
    HIMC=System.IntPtr
    HINSTANCE=System.IntPtr
    HKEY=System.IntPtr
    HLOCAL=System.IntPtr
    HMENU=System.IntPtr
    HMETAFILE=System.IntPtr
    HMODULE=System.IntPtr
    HMONITOR=System.IntPtr
    HPALETTE=System.IntPtr
    HPEN=System.IntPtr
    HRGN=System.IntPtr
    HRSRC=System.IntPtr
    HSZ=System.IntPtr
    HWINSTA=System.IntPtr
    HWND=System.IntPtr
    INT=System.Int32
    INT32=System.Int32
    INT64=System.Int64
    LONG=System.Int32
    LONG32=System.Int32
    LONG64=System.Int64
    LONGLONG=System.Int64
    LPARAM=System.IntPtr
    LPBOOL=System.Int16[]
    LPBYTE=System.UInt16[]
    LPCOLORREF=System.UInt32[]
    LPCSTR=System.String
    LPCTSTR=System.String
    LPCVOID=System.UInt32
    LPCWSTR=System.String
    LPDWORD=System.UInt32[]
    LPHANDLE=System.UInt32
    LPINT=System.Int32[]
    LPLONG=System.Int32[]
    LPSTR=System.String
    LPTSTR=System.String
    LPVOID=System.UInt32
    LPWORD=System.Int32[]
    LPWSTR=System.String
    LRESULT=System.IntPtr
    PBOOL=System.Int16[]
    PBOOLEAN=System.Int16[]
    PBYTE=System.UInt16[]
    PCHAR=System.Char[]
    PCSTR=System.String
    PCTSTR=System.String
    PCWCH=System.UInt32
    PCWSTR=System.UInt32
    PDWORD=System.Int32[]
    PFLOAT=System.Float[]
    PHANDLE=System.UInt32
    PHKEY=System.UInt32
    PINT=System.Int32[]
    PLCID=System.UInt32
    PLONG=System.Int32[]
    PLUID=System.UInt32
    PSHORT=System.Int16[]
    PSTR=System.String
    PTBYTE=System.Char[]
    PTCHAR=System.Char[]
    PTSTR=System.String
    PUCHAR=System.Char[]
    PUINT=System.UInt32[]
    PULONG=System.UInt32[]
    PUSHORT=System.UInt16[]
    PVOID=System.UInt32
    PWCHAR=System.Char[]
    PWORD=System.Int16[]
    PWSTR=System.String
    REGSAM=System.UInt32
    SC_HANDLE=System.IntPtr
    SC_LOCK=System.IntPtr
    SHORT=System.Int16
    SIZE_T=System.UInt32
    SSIZE_=System.UInt32
    TBYTE=System.Char
    TCHAR=System.Char
    UCHAR=System.Byte
    UINT=System.UInt32
    UINT32=System.UInt32
    UINT64=System.UInt64
    ULONG=System.UInt32
    ULONG32=System.UInt32
    ULONG64=System.UInt64
    ULONGLONG=System.UInt64
    USHORT=System.UInt16
    WORD=System.UInt16
    WPARAM=System.IntPtr 
    附:举一个声明API的例子[ DllImport( "Kernel32.dll" )]
    public static extern System.UInt32 VirtualAllocEx(
    System.IntPtr hProcess,
    System.UInt32 lpAddress,
    System.UInt32 dwSize,
    System.UInt32 flAllocationType,
    System.UInt32 flProtect
    );
      

  3.   

    我要的结果就是 我要改变databuff32的值
      

  4.   

    函数原型是 
    short NfcSingleTagIdentity (HANDLE hCom,unsigned int TagType,unsigned char *Id)
      

  5.   


     public static extern uint NfcMultipleTagIdentify(IntPtr icdev, int cnt, ref KeyBuf Tags);
     public struct KeyBuf
      {
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
                public string c;
    }IntPtr icdev = new IntPtr(0);
      

  6.   

    记得输出的字符串好像要传StringBuilder对象。
      

  7.   

    这些我都写在我自定义的CLASS里
    那请问我在前台该怎么调用呢 最后一个参数报错
    Class1.NfcSingleTagIdentify((IntPtr)icdev, 4,ref databuff32);
      

  8.   

    IntPtr   icdev   =   new   IntPtr(0);
    uint rt=0;
    Class1.KeyBuf databuff32=new Class1.KeyBuf();
    rt=Class1.NfcSingleTagIdentify(icdev   ,   4,ref   databuff32);