youyundao 发表于 2007-8-1 11:27:34

关于在C#中调用C++ DLL 时的参数传递

近日在C#中调用C++DLL的接口时,遇到了一些参数传递的问题,几经探索,问题终于解决,现整理如下,希望对各位
P(rogrammer)友有所帮助:

如果DLL接口的输入参数为char**,也就是字符数组的数组(即字符串数组),此时在C#声明中不能直接传递string[],传递的应该是通过Encoding类对这个string[]进行编码后得到的一个char[]。

如果DLL接口的输出参数为char**,也就是字符数组的数组(即字符串数组),此时在C#声明中应该使用byte[]来做参数。然后通过Encoding类对这个byte[]进行解码,得到字符串。如下例所示:

C++ DLL接口:

long _stdcall USE_GetAgentGroupInfoEx(
/*   */ char** AgentID,
/*   */ long ArraySize,
/* */ char** AgentName,
/* */ long AgentStatus[],
/* */ char** AgentDN,
/* */ char** AgentIP);

C#中的声明


public static extern int USE_GetAgentGroupInfoEx
(
        /**/ char[]        allAgentID,
        /**/ int                agentCount,
        /**/ byte[]        AgentName,
        /**/ int[]        AgentStatus,
        /**/ byte[]        AgentDN,
        /**/ byte[]        AgentIP
);

C#中的调用:

Encoding encode = Encoding.Default;
byte[]        tAgentID;
byte[]        tAgentName;
int[]        tAgentStatus;
byte[]        tAgentDN;
byte[]        tAgentIP;

int rslt = -1;
int agentCount;

//agentID:是个外部定义的string[]类型变量
//AgentName:是个外部定义的string[]类型变量
//AgtIDLength:是C++ DLL中定义的存放AgtID的char[]的长度
//AgtNameLength:是C++ DLL中定义的存放AgtName的char[]的长度
//AgtDNLength:是C++ DLL中定义的存放AgtDN的char[]的长度
//AgtIPLength:是C++ DLL中定义的存放AgtIP的char[]的长度

if (agentID.Length > 0)
{
        agentCount        = agentID.Length;
        tAgentID                = new byte;
        tAgentName        = new byte;
        tAgentStatus        = new int;
        tAgentDN                = new byte;
        tAgentIP                = new byte;
        for( int i = 0; i < agentCount; i ++ )
        {
encode.GetBytes(agentID).CopyTo(tAgentID,i*AgtIDLength);
        }
rslt = USE_GetAgentGroupInfoEx(encode.GetChars(tAgentID),agentCount,
tAgentName, tAgentStatus, tAgentDN, tAgentIP);

        if( rslt == 0 )
        {
                for( int i = 0; i < agentCount; i ++ )
                {
        AgentName        = encode.GetString(tAgentName,i*AgtNameLength,AgtNameLength);
                         //……
                }
}
}

对于基本的数值类型的数据,如果是输入参数,则直接按值传递,如果是输出参数,则需要按引用传递(加ref 修饰)。

不论什么类型的数组,传递时实际上都是按引用传递,所以不需要再用ref修饰,否则会出错。对于传出型参数,在调用前要记得分派足够的空间。

lchq_zj 发表于 2007-9-6 14:19:06

由于你要访问的是C++代码----非托管代码(不安全代码)  所以建议你把访问C++的代码写到unsafe 里面试下

chenlunpan 发表于 2007-9-6 15:57:11

还没搞过..

yining 发表于 2007-9-7 11:39:43

char**对应的是string[]

oracle_8i 发表于 2007-9-7 17:44:05

问一下楼主,如果从C++中接受返回数据类型,比如结构体,C#中该如何处理?

twriter 发表于 2009-11-12 20:32:11

参照:
int 类型

//返回个int 类型
public static extern int mySum (int a1,int b1);
//DLL中申明
extern “C” __declspec(dllexport)int WINAPI mySum(int a2,int b2)
{
//a2 b2不能改变a1 b1
//a2=..
//b2=...
return a+b;
}


//参数传递int 类型
public static extern int mySum (ref int a1,ref int b1);
//DLL中申明
extern “C” __declspec(dllexport)int WINAPI mySum(int *a2,int *b2)
{
//可以改变 a1, b1
*a2=...
*b2=...
return a+b;
}
页: [1]
查看完整版本: 关于在C#中调用C++ DLL 时的参数传递