110,534
社区成员
发帖
与我相关
我的任务
分享
public class TManagerFactory
{
private int FLib = 0;
private TMTManGetVersion FGetVersion = null;
private TMTManGetInterface FGetInterface = null;
protected IManagerInterface FResult = null;
public TManagerFactory(string dll) : base()
{
FLib = LoadLibrary(dll);
if (FLib == 0)
Console.WriteLine("加載出錯");
FGetVersion = (TMTManGetVersion)GetAddress(FLib, "MtManVersion", typeof(TMTManGetVersion));
FGetInterface = (TMTManGetInterface)GetAddress(FLib, "MtManCreate", typeof(TMTManGetInterface));
}
public IManagerInterface CreateAPI()
{
if ((FGetVersion != null) && (FGetInterface != null))
{
FGetInterface(FGetVersion(), ref FResult);
}
else
{
FResult = null;
}
return FResult;
}
public int GetTMTManGetVersion()
{
return FGetVersion();
}
} // end TManagerFactory
public delegate int TMTManGetVersion();
public delegate int TMTManGetInterface(int Version, ref IManagerInterface Obj);
public interface IManagerInterface
{
int Connect(string Server);
int Login(int Login, string Password);
int PasswordChange(string Password, int IsInvestor);
//还有许多略
}
public class ManagerInterface : IManagerInterface
{
#region IManagerInterface 成员
public virtual int Connect(string Server)
{
return Connect(Server);
}
public virtual int Disconnect()
{
return Disconnect();
}
public virtual int IsConnected()
{
return IsConnected();
}
}
public class ConnectionApi : ManagerInterface
{
public override int PasswordChange(string Password, int IsInvestor)
{
string pathFile = AppDomain.CurrentDomain.BaseDirectory;
//簡單寫日誌
WriteFile("Psw:" + Password);
return PasswordChange(Password, IsInvestor);
}
public override int Login(int intLogin, string Password)
{
WriteFile(String.Format("Login:{0},Pwd:{1}", intLogin, Password));
return Login(intLogin, Password);
}
}
typedef int (*MtManVersion_t)(void);
typedef int (*MtManCreate_t)(int version,CManagerInterface **man);
class CManagerInterface
{
public:
//---- dummy methods for delphi
virtual int __stdcall QueryInterface(REFIID riid,LPVOID* obj)=0;
virtual int __stdcall AddRef() =0;
//---- release
virtual int __stdcall Release()=0;
//---- service methods
virtual void __stdcall MemFree(void* ptr) =0;
virtual LPCSTR __stdcall ErrorDescription(const int code)=0;
virtual void __stdcall WorkingDirectory(LPCSTR path) =0;
//---- connection
virtual int __stdcall Connect(LPCSTR server) =0;
virtual int __stdcall Disconnect() =0;
virtual int __stdcall IsConnected() =0;
virtual int __stdcall Login(const int login,LPCSTR password)=0;
//--还有许多方法略
public struct user_group_t
{
public int id;
public string name;
}
public struct user_group_list
{
public int group_array_count;
public IntPtr group_array;//指向 user_group_t类型的指针
}
//泛型函数实现转换功能
public static List<T> MarshalPtrToStructArray<T>(IntPtr p, int count)
{
List<T> l = new List<T>();
for (int i = 0; i < count; i++, p = new IntPtr(p.ToInt32() + Marshal.SizeOf(typeof(T))))
{
T t = (T)Marshal.PtrToStructure(p, typeof(T));
l.Add(t);
}
return l;
}
调用方式
通常C++函数返回一个指向user_group_list类型的指针,在C#中可使用IntPtr ptrGroupList对应指针,而user_group_list类型结构体内包含的内容是长度为 group_array_count,地址为 group_array 的数组
因为IntPtr不能如C++的指针一样进行 ptrGroupList++这样的操作,所以要访问其内部成员需要把它转换为数组或list 使用Marshal.PtrToStructure把指向结构体的指针转换为具体的结构体
user_group_list tructList = (user_group_list)Marshal.PtrToStructure(ptrStructGroupList, typeof(user_group_list));
再使用泛型转换函数实现转换
List<user_group_t> listGroupTemp = MarshalPtrToStructArray<user_group_t>(structList.group_array, structList.group_array_count);
具它参考资料 http://tcspecial.iteye.com/blog/1675621
[DllImport("your.dll")]
static extern int RecordTest(TRecordTest[] data, int length);
void Test()
{
TRecordTest[] data = new TRecordTest[5];
int count = RecordTest(data, data.Length);
}
public struct TTestRecord
{
public int aInt;
// ip
public double aDouble;
}
public delegate int TRecordTest(ref TTestRecord[] record);
//按钮事件
TRecordTest temp = (TRecordTest)DLLWrapper.GetFunctionAddress(hModule, "RecordTest", typeof(TRecordTest));
TTestRecord var1 = new TTestRecord();
var1.aInt = 0;
var1.aDouble = 0;
ArrayList arr = new ArrayList();
arr.Add(var1);
TTestRecord[] structArr = (TTestRecord[])arr.ToArray(typeof(TTestRecord));
int t = temp(ref structArr);
string aIntTest="";
for (int i = 0; i < structArr.Length; i++)
{
TTestRecord testRecord = structArr[i];
aIntTest += "aInt:" + testRecord.aInt + "aDouble:" + testRecord.aDouble+"";
}
用上面代码测试,用ref 返回结构体数组长度仅1(这是错误C函数数组有许多),用out(虽不用声明,但返回不出任何结构体数组),求解.
说明函数RecordTest
virtual int __stdcall RecordTest(TTestRecord *cfg)=0;
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComImport]
interface CManagerInterface
{
void MemFree(IntPtr ptr);
IntPtr ErrorDescription(int code);
...
}