gpt4 book ai didi

c# - 将带有 char* 的结构编码到 C#

转载 作者:行者123 更新时间:2023-11-30 17:51:11 25 4
gpt4 key购买 nike

我在 C 程序中使用了以下结构

typedef enum
{
ndberror_st_success = 0,
ndberror_st_temporary = 1,
ndberror_st_permanent = 2,
ndberror_st_unknown = 3
} ndberror_status_enum;

typedef enum
{
ndberror_cl_none = 0,
ndberror_cl_application = 1,
ndberror_cl_no_data_found = 2,
ndberror_cl_constraint_violation = 3,
ndberror_cl_schema_error = 4,
ndberror_cl_user_defined = 5,
ndberror_cl_insufficient_space = 6,
ndberror_cl_temporary_resource = 7,
ndberror_cl_node_recovery = 8,
ndberror_cl_overload = 9,
ndberror_cl_timeout_expired = 10,
ndberror_cl_unknown_result = 11,
ndberror_cl_internal_error = 12,
ndberror_cl_function_not_implemented = 13,
ndberror_cl_unknown_error_code = 14,
ndberror_cl_node_shutdown = 15,
ndberror_cl_configuration = 16,
ndberror_cl_schema_object_already_exists = 17,
ndberror_cl_internal_temporary = 18
} ndberror_classification_enum;


typedef struct {
ndberror_status_enum status;
ndberror_classification_enum classification;
int code;
int mysql_code;
const char * message;
char * details;
} ndberror_struct;

我需要在 C# 程序中编码它,C# 端声明是:

    public enum ndberror_status
{
ndberror_st_success = 0,
ndberror_st_temporary = 1,
ndberror_st_permanent = 2,
ndberror_st_unknown = 3,
}

public enum ndberror_classification
{
ndberror_cl_none = 0,
ndberror_cl_application = 1,
ndberror_cl_no_data_found = 2,
ndberror_cl_constraint_violation = 3,
ndberror_cl_schema_error = 4,
ndberror_cl_user_defined = 5,
ndberror_cl_insufficient_space = 6,
ndberror_cl_temporary_resource = 7,
ndberror_cl_node_recovery = 8,
ndberror_cl_overload = 9,
ndberror_cl_timeout_expired = 10,
ndberror_cl_unknown_result = 11,
ndberror_cl_internal_error = 12,
ndberror_cl_function_not_implemented = 13,
ndberror_cl_unknown_error_code = 14,
ndberror_cl_node_shutdown = 15,
ndberror_cl_configuration = 16,
ndberror_cl_schema_object_already_exists = 17,
ndberror_cl_internal_temporary = 18,
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct ndberror_struct
{
public ndberror_status status;
public ndberror_classification classification;
public int code;
public int mysql_code;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string message;
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string details;
}

要调用的方法的C端签名是:

const ndberror_struct __stdcall Ndb_getNdbError(void* obj);

C# 端是:

        [System.Runtime.InteropServices.DllImportAttribute("Ndb_CWrapper.dll", EntryPoint = "Ndb_getNdbError", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall,CharSet = CharSet.Ansi)]
private static extern ndberror_struct Ndb_getNdbError(System.IntPtr obj);

当我尝试从托管代码调用该方法时,会引发 MarshalDirectiveException。我认为问题出在字符串编码的某个地方,但我无法解决问题。 native 库是为 x64 系统多字节字符集代码编译的(使用 visual studio c++ 2012)

另一种方法是在 native 代码中进行一些奇怪的操作,我将 NdbError(在另一个 header 中定义)转换为 ndberror_struct,这里是代码:

Ndb* tmp=(Ndb*)obj;
ndberror_struct tmpRes=(ndberror_struct)tmp->getNdbError();

tmp->getNdbError() 返回的 NdbStruct 重载了转换运算符(我想),这是声明:

operator ndberror_struct() const {
ndberror_struct ndberror;
ndberror.status = (ndberror_status_enum) status;
ndberror.classification = (ndberror_classification_enum) classification;
ndberror.code = code;
ndberror.mysql_code = mysql_code;
ndberror.message = message;
ndberror.details = details;
return ndberror;
}

我们将不胜感激。

编辑:我试图以这种方式稍微更改方法的签名:C端:

void* __stdcall Ndb_getNdbError(void* obj)

C#端:

IntPtr Ndb_getNdbError(IntPtr obj)

native 方法返回 &tmpRes 并且在托管代码中我手动编码了结构调用

var tmp=Ndb_getNdbError(raw);
var f = (ndberror_struct)Marshal.PtrToStructure(tmp, typeof(ndberror_struct));

最佳答案

编码器不会将那些 char* 字段从 native 代码编码到托管代码。你必须自己做那一点。

一种方法是更改​​ C# 结构声明,如下所示:

public struct ndberror_struct
{
public ndberror_status status;
public ndberror_classification classification;
public int code;
public int mysql_code;
public IntPtr message;
public IntPtr details;
}

保留你的 p/invoke 声明:

[DllImport("Ndb_CWrapper.dll")]
private static extern ndberror_struct Ndb_getNdbError(IntPtr obj);

您现在可以调用该函数了。为了将两个 IntPtr 字段转换为字符串,调用 Marshal.PtrToStringAnsi

关于c# - 将带有 char* 的结构编码到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19810763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com