从C#调用C DLL函数

发布于 2025-02-10 16:23:46 字数 2273 浏览 1 评论 0原文

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 = "[email protected]";
            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吗?

A C dll has:

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];
};

I need to call a function in this dll from my C# code, which has the following signature:
__declspec(dllexport) MyErrCode CheckUser(const struct CredData* cred_data, const struct EndpointData* endpoint_data);

Here is what I have tried:

I first declared the corresponding types in 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;
    }

Later declared the function as:

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

and then call the function as:

CredData objCredData = new CredData();
            objCredData.credType = CredType.PAIR;
            CredPair objPair = new CredPair();
            objPair.usr = "[email protected]";
            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);

But looks like parameters are not received correctly.
What parameters are wrong here? I believed void* in struct will become IntPtr in C#. The functions also need pointers to structure. Will that also have to be converted to IntPtr?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

镜花水月 2025-02-17 16:23:46

您需要在Pinvoke声明中遇到许多问题,

  • 您需要确保释放HGLobal内存,否则会泄漏。
  • 字符串被声明为固定大小char c中的数组,因此需要为charset.ansi ...
  • ...并且需要声明它们[MARSHALAS (unmanagedtype.byvaltstr,sizeconst = 127)],因此它们具有固定的嵌套大小。
  • 该功能的参数需要为ref,也可能使用[in]属性。
  • 您需要naterconvention = callconvention.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 = "[email protected]"
        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);
}

You have a number of issues with your PInvoke declarations

  • You need to make sure to free your HGlobal memory, otherwise it will leak.
  • The strings are declared as fixed size char arrays in C, so need to be CharSet.Ansi...
  • ... and they need to be declared [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 127)] so they have fixed nested size.
  • The parameters to the function need to be ref, possibly with [In] attribute also.
  • You need 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 = "[email protected]"
        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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文