繁体   English   中英

从 C# 调用 C dll 函数

[英]Call C dll function from C#

AC dll有:

struct CredPair{
    char usr[127];
    char pas[127];
};

struct CredData{
    enum CredType {
        PAIR,
        KEY
    } credType;

    void* CredVal;
};

struct EndpointData {
    enum EndpointType {
        DIRECT  
    } endpointType;
  
    void* endpointVal;
};

struct EndpointDirect {
    char url[127];
};

我需要从我的 C# 代码中调用此 dll 中的一个函数,该函数具有以下签名: __declspec(dllexport) MyErrCode CheckUser(const struct CredData* cred_data, const struct EndpointData* endpoint_data);

这是我尝试过的:

我首先在 C# 中声明了相应的类型:

public struct CredPair
    {
        public string usr;
        public string pas;
    }
public enum CredType 
    {
        PAIR,
        KEY
    } 

public struct EndpointDirect 
    {
        public string url;
    }

public enum EndpointType
    {
        DIRECT
    }

public struct CredData
    {
        public CredType credType;
        public IntPtr credVal;
    }

public struct EndpointData {
        public EndpointType endpointType;
        public IntPtr endpointVal;
    }

后来将该函数声明为:

[DllImport("mydll.dll")]
public static extern MyErrCode CheckUser(CredData cred_Data, EndpointData endpoint_data);

然后将函数调用为:

CredData objCredData = new CredData();
            objCredData.credType = CredType.PAIR;
            CredPair objPair = new CredPair();
            objPair.usr = "abc@xyz.com";
            objPair.pas = "admin@1234";
            IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(objPair));
            Marshal.StructureToPtr(objPair, pnt, false);
            objCredData.credentialValue = pnt;

            EndpointData objData = new EndpointData ();
            objData.endpointType = EndpointType.DIRECT;
EndpointDirect epd = new EndpointDirect ();
            epd.url = "example.com";
            IntPtr urlptr = Marshal.AllocHGlobal(Marshal.SizeOf(epd));
            Marshal.StructureToPtr(epd, urlptr, false);
    objData.endpointValue = urlptr;

error_code = CheckUser(objCredData, objData);

但看起来参数没有正确接收。 这里哪些参数有问题? 我相信 struct 中的 void* 将成为 C# 中的 IntPtr。 这些函数还需要指向结构的指针。 这也必须转换为 IntPtr 吗?

您的 PInvoke 声明存在许多问题

  • 你需要确保释放你的 HGlobal 内存,否则它会泄漏。
  • 字符串在 C 中被声明为固定大小的char数组,因此需要是CharSet.Ansi ...
  • ...并且它们需要被声明为[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 127)]以便它们具有固定的嵌套大小。
  • 函数的参数需要是ref ,也可能带有[In]属性。
  • 你需要CallingConvention = CallingConvention.Cdecl
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CredPair
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 127)]
        public string usr;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 127)]
        public string pas;
    }

public enum CredType 
    {
        PAIR,
        KEY
    } 

public enum EndpointType
    {
        DIRECT
    }

public struct CredData
    {
        public CredType credType;
        public IntPtr credVal;
    }

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct EndpointDirect
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 127)]
        public string url;
    }

public struct EndpointData
    {
        public EndpointType endpointType;
        public IntPtr endpointVal;
    }
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern MyErrCode CheckUser([In] ref CredData cred_Data, [In] ref EndpointData endpoint_data);
IntPtr pnt;
IntPtr urlptr;
try
{
    CredPair objPair = new CredPair
    {
        usr = "abc@xyz.com"
        pas = "admin@1234",
    };
    pnt = Marshal.AllocHGlobal(Marshal.SizeOf(objPair));
    Marshal.StructureToPtr(objPair, pnt, false);
    CredData objCredData = new CredData
    {
        credType = CredType.PAIR,
        credVal = pnt,
    };

    endpointValue = new EndpointDirect
    {
        url = "example.com",
    };
    urlptr = Marshal.AllocHGlobal(Marshal.SizeOf(epd));
    Marshal.StructureToPtr(epd, urlptr, false);
    EndpointData objData = new EndpointData
    {
        endpointType = EndpointType.DIRECT,
        endpointValue = urlptr,
    };

    error_code = CheckUser(ref objCredData, ref objData);
}
finally
{
    Marshal.FreeHGlobal(pnt);
    Marshal.FreeHGlobal(urlptr);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM