关于C#调用带有回调参数的API

时间:2022-11-06 19:01:18
这几天使用C#调用PB API来分析pb的源代码文件,(在此严重鄙视PB,人家的源码都是文本,就你的非要自己捣鼓),其中一个API原型是这样的

int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 


参数说明

 
hORCASession 
 Handle to previously established ORCA session 
 
lpszLibName 
 Pointer to a string whose value is the filename of the library for which you want directory information 
 
lpszLibComments 
 Pointer to a buffer in which ORCA will put comments stored with the library 
 
iCmntsBuffSize 
 Size of the buffer pointed to by lpszLibComments 
 
pListProc 
 Pointer to the PBORCA_LibraryDirectory callback function. The callback function is called for each entry in the library 
The information ORCA passes to the callback function is entry name, comments, size of entry, and modification time, stored in a structure of type PBORCA_DIRENTRY 

 
pUserData 
 Pointer to user data to be passed to the PBORCA_LibraryDirectory callback function 
The user data typically includes the buffer or a pointer to the buffer in which the callback function formats the directory information as well as information about the size of the buffer 
 
其中pListProc作为回调函数,定义如下

typedef void (FAR PASCAL *PBORCA_LISTPROC) ( PPBORCA_DIRENTRY, LPVOID ); 

参数说明
PPBORCA_DIRENTRY 
 Pointer to the structure PBORCA_DIRENTRY, described next 
 
LPVOID 
 Long pointer to user data  
结构体PBORCA_DIRENTRY structure如下
typedef struct pborca_direntry 

CHAR szComments[PBORCA_MAXCOMMENT + 1]; 
LONG lCreateTime; 
LONG lEntrySize; 
LPSTR lpszEntryName;
 PBORCA_TYPE otEntryType;} 
PBORCA_DIRENTRY, FAR *PPBORCA_DIRENTRY; 

以上的详细参考资料在
http://manuals.sybase.com/onlinebooks/group-pb/adt0650e/orca/@Generic__BookTextView/7001;pt=4344;lang=zh#X


49 个解决方案

#1


然后我市这样声名的

函数
 [DllImport("pborc90.dll", EntryPoint = "PBORCA_LibraryDirectory")]
        public static extern int EntryList(uint sessionId, string libName, StringBuilder libComents, int comentSize, dele_test treatFunc, uint UserData); 
    
两个结构体     
 [StructLayout(LayoutKind.Sequential)]
    public struct ORCA_UserDataInfo
    {
      //  public char[] entryInfo; // Buffer for entry info
        public uint dwCallCount; // # of entries in lib
        public uint dwBufferSize; // size of buffer
        public uint dwBufferOffset; // current offset in buffer
    }
    [StructLayout(LayoutKind.Sequential)]
   public struct PBORCA_DIRENTRY
    {
     public   char[] szComments; // Buffer for entry info
        public int lCreateTime; // # of entries in lib
        public int lEntrySize; // size of buffer
        public string lpszEntryName; // current offset in buffer
        public uint otEntryType;

    }

委托
    public delegate void dele_test(PBORCA_DIRENTRY entryInfo, uint udInfo);

调用过程
uint sessionId;
                sessionId = OpenSession();
                int returnValue;
            StringBuilder sbComment=new StringBuilder (5000);
            dele_test dele_t1 = new dele_test(treatEntryInfo);
            ORCA_UserDataInfo udi=new ORCA_UserDataInfo ();
                   PBORCA_DIRENTRY pd = new PBORCA_DIRENTRY();
           returnValue= EntryList(sessionId, "c:\\ihatepb.pbl", sbComment, sbComment.Length, dele_t1,0);

结果出来各种奇怪的错误,有什么数组与元数据不符,或者数组类型错误,或者内存不能写等等。
总之就是数据类型对照有错误。
请各位老师不吝赐教,谢谢


#2


回调函数在C#里要定义成委托类型

#3


[StructLayout(LayoutKind.Sequential)] 
    public struct ORCA_UserDataInfo 
    { 
      //  public char[] entryInfo; // Buffer for entry info 
        public uint dwCallCount; // # of entries in lib 
        public uint dwBufferSize; // size of buffer 
        public uint dwBufferOffset; // current offset in buffer 
    } 
    [StructLayout(LayoutKind.Sequential)] 
  public struct PBORCA_DIRENTRY 
    { 
    public  char[] szComments; // Buffer for entry info 
        public int lCreateTime; // # of entries in lib 
        public int lEntrySize; // size of buffer 
        public string lpszEntryName; // current offset in buffer 
        public uint otEntryType; 

    } 
=====================
这两个结构里面的 char[]  都要定义长度

#4


public static extern int EntryList(uint sessionId, string libName, StringBuilder libComents, int comentSize, dele_test treatFunc, uint UserData); 

这里的 LPSTR 你知道用 StringBuilder

那public struct PBORCA_DIRENTRY 这里的public string lpszEntryName;为啥不用

#5


C\C++ 中的 char是类型一个字节

C# 中的 char类型,所以转换的时候要用byte取代C\C++中的char

大概是这样:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)]
public  byte[] szComments; // Buffer for entry info 

参考EnumWindows标准API回调的使用:

using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[DllImport("user32.dll")]
public static extern int EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);

public static bool EnumFunc(IntPtr hwnd, int lParam)
{
    Console.WriteLine("Window handle is " + hwnd);
    return true;
}

private void button1_Click(object sender, EventArgs e)
{
    EnumWindows(EnumFunc, 0);
}

#6


C# 中的 char类型两个字节。

#7


十分感谢大家的积极回复。
现就大家提出的方法解释一下
 eglic 
你提出的问题,第一,我在结构体里面定义char[]entry=new char[50];地时候,编译提示结构体中不允许初始化(我是英文vs,可能翻译的不准确)
第二,我第一次用stringbuilder,但是运行时提示stringbuilder 不能用在结构体中,让我用初始化的string代替,我想string肯定不行了,那就只好用char凑合

zswang 我先回复,然后再详细看你的例子。
感谢各位的帮助

#8


提出的问题,第一,我在结构体里面定义char[]entry=new char[50];地时候,编译提示结构体中不允许初始化(我是英文vs,可能翻译的不准确) 

用Marshal....

  public struct PBORCA_DIRENTRY 
    { 
    [MarshalAs(SizeConst=50)]
    public  char[] szComments; // Buffer for entry info 
        public int lCreateTime; // # of entries in lib 
        public int lEntrySize; // size of buffer 
        public string lpszEntryName; // current offset in buffer 
        public uint otEntryType; 

    } 

#9


using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[DllImport("user32.dll")]
public static extern int EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);

public static bool EnumFunc(IntPtr hwnd, int lParam)
{
    Console.WriteLine("Window handle is " + hwnd);
    return true;
}

private void button1_Click(object sender, EventArgs e)
{
    EnumWindows(EnumFunc, 0);
}

这段代码我基本看懂了,但是有几个地方跟我预期的有出入
1声名的时候声名的是一个委托WNDENUMPROC ,传递的时候是传函数名。
我声明的时候也是一个委托,但是传的时候使用的是委托的实例。不知道我这种有没有问题
2intptr字面意思应该是整数指针的意思,那么他跟ulong是不是可以互换?有什么特殊性?
3 我觉得关键是那几个struct怎么声明和调用。

再次感谢您。

#10


int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 

从函数原型的字面意思很难猜出 LPSTR lpszLibName, LPSTR lpszLibComments
这两个是传入还是传出了

传入用 string就可以了
传出用 StringBuilder

PBORCA_DIRENTRY这个结构里面的 LPSTR lpszEntryName; 
这个可能会有点麻烦,这个应该是传出一个字符串
如果文档中没有定义的话,那这个应该是传出一个指针

你可以尝试定义为 IntPtr,然后用
Marshal.PtrToStringAnsi 
或者 PtrToStringAuto 或者 PtrToStringBSTR  或者 PtrToStringUni 转换一下

#11


eglic 

Error 2 'System.Runtime.InteropServices.MarshalAsAttribute' does not contain a constructor that takes '0' arguments E:\My Document\Visual Studio 2008\Projects\PBORCATry\PBORCATry\Program.cs 160 10 PBORCATry

#12


引用 11 楼 phyloinker 的回复:
eglic 

Error 2 'System.Runtime.InteropServices.MarshalAsAttribute' does not contain a constructor that takes '0' arguments E:\My Document\Visual Studio 2008\Projects\PBORCATry\PBORCATry\Program.cs 160 10 PBORCATry 


楼上已经有人给出完整的了

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)] 

#13


int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 

从函数原型的字面意思很难猜出 LPSTR lpszLibName, LPSTR lpszLibComments 
这两个是传入还是传出了 

hORCASession,传入 lpszlibName,lpszLibComments 传出 iCmntsBuffSize 传入 pListProc回调函数
pUserData 

Pointer to user data to be passed to the PBORCA_LibraryDirectory callback function 
The user data typically includes the buffer or a pointer to the buffer in which the callback function formats the directory information as well as information about the size of the buffer 

我英文不好,硬是没看到这个字段时干吗用的。感觉上应该是一个传出的。用来保存directory infomation的。

#14


楼上各位的指教我会好好消化
现在还有一个问题
就是

int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 
 LPVOID pUserData 这个东西我声明的时候市声明称
uint UserData

还是我自定义的结构体类型
ORCA_UserDataInfo UserData?

还有那个回调函数的原型
typedef void (FAR PASCAL *PBORCA_LISTPROC) ( PPBORCA_DIRENTRY, LPVOID ); 
PPBORCA_DIRENTRY  //定义的结构体

LPVOID //刚才那个ORCA_UserDataInfo结构体
 
这两个参数我在定义的时候是定义成


 public delegate void dele_test(PBORCA_DIRENTRY entryInfo, ORCA_UserDataInfo udInfo);
还是
 public delegate void dele_test(uint entryInfo, uint udInfo);
或者是
 public delegate void dele_test(intptr entryInfo, intptr udInfo);

第一次正儿八经的写API的应用,请包涵

#15


哈哈,按照大家的指示
char改撑byte
传委托的实例改成传函数名
还有那个marshell
虽然结果还不正确,但是起码不抱错了。十分感谢各位指导!尤其感谢eglic  

#16


声明的时候尽量接近原型

用IntPtr是万不得已的情况,遇上了变态的API。。。

#17


这个只能你自己多实验了,反正就那么几种办法,一个不行换一个再试试

#18


引用 5 楼 zswang 的回复:
C\C++ 中的 char是类型一个字节 

C# 中的 char类型,所以转换的时候要用byte取代C\C++中的char 

大概是这样: 

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)] 
public byte[] szComments; // Buffer for entry info 

参考EnumWindows标准API回调的使用: 

C# code
using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[Dll…



帮顶

#19


运行时不抱错了,但是传给回调函数的都是空值………………
痛苦啊!
知识到用时方恨少

#20


哇   高手!!!!

#21


而且倒了回调函数运行完毕之后,没有返回主调用那个地方继续运行,直接停在那里了………………是不是关于回调我还有什么没注意的…………

#22


typedef struct ORCA_UserDataInfo
{
LPSTR lpszBuffer; // Buffer for entry info
DWORD dwCallCount; // # of entries in lib
DWORD dwBufferSize; // size of buffer
DWORD dwBufferOffset; // current offset in buffer
} ORCA_USERDATAINFO, FAR *PORCA_USERDATAINFO;

这是例子中的结构体的定义
我转成了
 [StructLayout(LayoutKind.Sequential)]
    public struct ORCA_UserDataInfo
    {

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)] 
        public byte[] entryInfo; // Buffer for entry info
        public uint dwCallCount; // # of entries in lib
        public uint dwBufferSize; // size of buffer
        public uint dwBufferOffset; // current offset in buffer
    }

结果是我调整那个SizeConst = 200,就会得到不同的结果,有时候是写保护,有时候时空,有时候能有值但是不知道对不对。

这四个成员应该都是输出方向的,是不是要加ref或者out之类的?

#23


原文中是这样的

CHAR szComments[PBORCA_MAXCOMMENT + 1]; 

所以你应该先找到 PBORCA_MAXCOMMENT 这个的定义

#24


坦白的说,我没找到PBORCA_MAXCOMMENT
但是我估计他是指得comment的最大值,我只要把它设置成足够大应该就可以了。

他给了一个例子
ORCA_USERDATAINFO UserDataBuffer;
PORCA_USERDATAINFO lpUserDataBuffer;
CHAR InfoBuffer[60000];
LPSTR pszLibraryName;
CHAR szComments[PBORCA_MAXCOMMENT];

// Set library name
pszLibraryName = "c:\\myapp\\ver1\\datamod.pbl";

// Initialize UserDataBuffer
lpUserDataBuffer = &UserDataBuffer;

lpUserDataBuffer->dwCallCount = 0;
lpUserDataBuffer->dwBufferOffset = 0;
lpUserDataBuffer->dwBufferSize = 60000;
lpUserDataBuffer->lpszBuffer = (LPSTR) InfoBuffer;

// Initialize all of InfoBuffer to 0
memset(lpUserDataBuffer->lpszBuffer,
0x00, (size_t) lpUserDataBuffer->dwBufferSize);

// Get the proc address of callback function
lpListProc = MakeProcInstance(
(FARPROC)LibraryList, hInst);

// Call ORCA function
lpORCA_Info->lReturnCode = PBORCA_LibraryDirectory(
lpORCA_Info->hORCASession, pszLibraryName,
(LPSTR) szComments, PBORCA_MAXCOMMENT,
(PBORCA_LISTPROC) lpListProc, lpUserDataBuffer);

//Release the proc instance resource
FreeProcInstance(lpListProc);


不过C语言的我看得不是很明白。但是我注意到
lpUserDataBuffer->lpszBuffer = (LPSTR) InfoBuffer;
也就是说结构体里面的第一个成员
LPSTR lpszBuffer; // Buffer for entry info 

实际上应该是一个指针,这样的话,我是不时就不应该定义成byte了?而应该定义成ulong或者inptr?
然后把它赋值到一个byte[]的首地址?
但是怎么取byte[]的首地址呢?

#25


PBORCA_MAXCOMMENT 是第一个结构体的,我刚才说的是第二个结构体,所以不牵扯PBORCA_MAXCOMMENT

#26


结构是一个固定长度的,所以你不可以将那个字符串设置的太长或者太短

你先找到第二个结构体的定义再说

#27


疯掉了。结贴送分,你不忙的话加我QQ165711698

#28


http://manuals.sybase.com/onlinebooks/group-pb/adt0650e/orca/@Generic__BookTextView/86;pt=45

在这里找到ORCA_USERDATAINFO的定义

typedef struct ORCA_UserDataInfo {
LPSTR lpszBuffer; // Buffer to store data 
DWORD dwCallCount; // # of messages in buffer 
DWORD dwBufferSize; // size of buffer 
DWORD dwBufferOffset; // current offset in buffer 
} ORCA_USERDATAINFO, FAR *PORCA_USERDATAINFO;

看来他是返回一个指针,你用IntPtr试试

然后在返回里面,用 string message=Marshal.PtrToStringANSI(ORCA_UserDataInfo.lpszBuffer,ORCA_UserDataInfo.dwBufferSize);

#29


哦,错了…………
上面不对,你可能需要用到 unsafe …………

它是预先定义一个buffer
然后把buffer的指针传过去


。。。。麻烦大了

#30


饿,学习了

#31


友情帮顶

#32


.......突然发现居然有幸得到版主垂青…………受宠若惊阿。
虽然已经结贴,其实还有有一些问题没解决。写出来供大家参考学习

 

#33


回调函数中结构体的原型
typedef struct pborca_direntry {
 TCHAR szComments[PBORCA_MAXCOMMENT + 1];
 LONG lCreateTime; 
LONG lEntrySize;
 LPSTR lpszEntryName; 
PBORCA_TYPE otEntryType;}
 PBORCA_DIRENTRY, FAR *PPBORCA_DIRENTRY;

对于里面的TCHAR和LPSTR的处理问题。
eglic 认为TCHAR可以直接用char[]也就是
 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public char[] szComments; // Buffer for entry info 
另外对结构体中的LPSTR lpszEntryName;
因为结构体中不允许使用stringBuilder
eglic 建议使用intPTR
但是不知道如何在回调函数中取得这个ptr指针指向地址的内容,现在还正在研究中。

欢迎各位继续发表高见,分当然就没有了。。。。

#34


LZ可以参考下我以前发的关于C#回调的帖子,虽然我的DELPHI与C#的,但相信还是对你有帮助的。
另外:你也许要补充下基础知识,就是关于函数DLL调用的标准,内存对不齐,是不可能调用正确的,参数类型上REF与IN、OUT是有区别的。

#35


回楼上,不是也许,是一定,初学者,见笑。
内存对齐的问题刚看了点介绍,正在准备学以致用
正在拜读您的大作。

#36


.NET Framework 开发人员指南  
如何:实现回调函数  

以下过程和示例演示托管应用程序如何使用平台调用来输出本地计算机上每个窗口的句柄值。尤其是,该过程和示例将使用 EnumWindows 函数来逐步浏览窗口列表,并使用一个托管回调函数(名为 CallBack)来输出窗口句柄的值。

实现回调函数

1. 开始实现之前,先查看 EnumWindows 函数的签名。EnumWindows 具有以下签名:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

表示此函数需要回调的线索之一是存在 lpEnumFunc 参数。如果参数采用指向回调函数的指针,其名称中通常会有 lp(长指针)前缀与 Func 后缀的组合。有关 Win32 函数的文档,请参见 Microsoft Platform SDK。 

2. 创建托管回调函数。该示例声明一个名为 CallBack 的委托类型,此委托类型采用两个参数:hwnd 和 lparam。第一个参数是窗口的句柄;第二个参数由应用程序定义。在此版本中,这两个参数都必须是整数。
回调函数通常会返回非零值来表示成功,返回零来表示失败。本示例将返回值显式设置为 true,以继续进行枚举。 

3. 创建一个委托,并将其作为参数传递给 EnumWindows 函数。平台调用会自动将委托转换为常见的回调格式。

4. 确保在回调函数完成其工作之前,垃圾回收器不会回收委托。如果委托作为参数进行传递,或者所包含的委托作为结构中的字段进行传递,则该委托在调用期间不会被回收。因此,正如下面的枚举示例所示,回调函数会在调用返回前完成其工作,而无需托管调用方执行额外的操作。 
然而,如果可以在调用返回后调用回调函数,则托管调用方必须采取相应的措施来确保委托在回调函数完成其工作之前不会被回收。有关防止垃圾回收的详细信息,请参见用平台调用进行 Interop 封送处理。 

示例
Imports System
Imports System.Runtime.InteropServices

Public Delegate Function CallBack( _
hwnd As Integer, lParam As Integer) As Boolean

Public Class EnumReportApp

    Declare Function EnumWindows Lib "user32" ( _
       x As CallBack, y As Integer) As Integer

    Public Shared Sub Main()
        EnumWindows(AddressOf EnumReportApp.Report, 0)
    End Sub 'Main

    Public Shared Function Report(hwnd As Integer, lParam As Integer) _
    As Boolean
        Console.Write("Window handle is ")
        Console.WriteLine(hwnd)
        Return True
    End Function 'Report
End Class 'EnumReportApp

using System;
using System.Runtime.InteropServices;

public delegate bool CallBack(int hwnd, int lParam);

public class EnumReportApp {

    [DllImport("user32")]
    public static extern int EnumWindows(CallBack x, int y); 

    public static void Main() 
    {
        CallBack myCallBack = new CallBack(EnumReportApp.Report);
        EnumWindows(myCallBack, 0);
    }

   public static bool Report(int hwnd, int lParam) { 
        Console.Write("Window handle is ");
        Console.WriteLine(hwnd);
        return true;
    }
}

using namespace System::Runtime::InteropServices;

// A delegate type.
__delegate bool CallBack(int hwnd, int lParam);

// Managed type with the method to call.
__gc class EnumReport 
{
// Report the window handle.
public:
    bool Report(int hwnd, int lParam) {
       Console::Write(L"Window handle is ");
       Console::WriteLine(hwnd);
       return true;
   }
};

[DllImport("user32")] 
extern "C" int EnumWindows(CallBack* x, int y); 

void main(void) { 
    EnumReport* er = new EnumReport;
    CallBack* myCallBack = new CallBack(er, &EnumReport::Report);
    EnumWindows(myCallBack, 0); 
}

#37


该回复于2008-11-06 04:01:51被版主删除

#38


经过peid分析,该dll为VC++连接器版本5.0

经查询vc默认内存对其模为8,枚举类型为4字节
那么我这样声明

 [StructLayout(LayoutKind.Sequential,Pack =8)]
        public struct PBORCA_DIRENTRY
        {
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public char[] szComments; // 原型 TCHAR      szComments[PBORCA_MAXCOMMENT + 1];
                                       //PBORCA_MAXCOMMENT =255
                                       
            public int lCreateTime; // 原型 LONG            lCreateTime;
            public int lEntrySize; // 原型 LONG            lEntrySize; 
            public IntPtr lpszEntryName; // 原型  LPTSTR       lpszEntryName;                   

            public  UInt32 otEntryType;//原型枚举类型

        }

但是结果依然不正确,请各位指正!

#39


该回复于2008-11-06 04:03:00被版主删除

#40


      奔驰宝马连线,动物转盘,水果机破解QQ690907862

技术一:
  适用于所有的狮子王国系列、彩金狮王系列、闪电王系列、飓风系列等。
  该技术在一年多前,曾有人向我请教过,我当时只是告诉他用400分或600分的平均压法。但具体的细节仍然做了保留,结果在后来网上流传的一个彩金狮王的技术压法就是400分或600分的平均压。甚至有人还拿这个来卖钱。
  结果显得非常可笑,因为所有拿到这个技术的人,都会陷入一个莫名的尴尬,就是比如投资400分,那么8分压50,5分压80分,出分都是400分,结果却发现400或600平均压法,总会压不完所有的动物,而导致每把亏分,跑什么都亏分,就算是放弃其中一或两种动物不压,每把也不能赚分,甚至跑到自己不压的那个动物,更是亏得血本无归。
  其实,400分的平均压法的真正原理是投入400分,每把都能赚100分左右。
  要彻底明白这个技术,你还应该知道的是:
  1、 这类连线机一般是最大46倍,最小4倍的系列。因为机器始终要保持正常的赢利,所以正常的机器一般出大小机率的比例是6:1左右,黑一点的老板一般把难度调高,难度调高后的大小比例一般在7或8:1,这里的“大”指的是出狮子或者熊猫的机率,“小”指的是出猴子和兔子的机率。
  2、 这类连线机只可能有3种版型,即兔子的倍数分别为:8、7、4和8、6、5以及5、6、7。
  
  所以针对不同的版型我们的压分方法应该如下:
  8、6、5版型:
  狮子的赔率分别为:46、35、28,熊猫的赔率为:23、17、14
  猴子的赔率为:13、10、8 兔子的赔率为:8、6、5
  于是压分的方法为(400分平均压):
  13猴子压39分:13X39==507 10猴子压50分:10X50==500
  8猴子和兔子压63分:8X63==504 6兔子压84分:6X84==504
  5的兔子压99分:5X99==495
  总压分为:39+50+63+63+84+99==398分
  
  7、6、5版型:
  狮子的赔率分别为:40、35、28,熊猫的赔率为:20、17、14
  猴子的赔率为:11、10、8 兔子的赔率为:7、6、5
  于是压分的方法为(400分平均压):
  11猴子压46分:11X46==506 10猴子压50分:10X50==500
  8猴子压63分:8X63==504 7的兔子压72分:7X72==504
  6兔子压84分:6X84==504 5的兔子压99分:5X99==495
  总压分为:46+50+63+72+84+99==414分
  
  8、7、4版型:
  狮子的赔率分别为:46、40、25,熊猫的赔率为:23、17、12
  猴子的赔率为:13、11、7 兔子的赔率为:8、7、4
  于是压分的方法为(400分平均压):
  13猴子压39分:13X39==507 11猴子压46分:11X46==506
  8猴子压63分:8X63==504 7的猴子和兔子压72分:7X72==504
  4的兔子压99分:4X99==396
  总压分为:39+45+63+72+72+99==390分
  
  从上面3种压分方法可以看出,每次投入的分值在400分左右,而出来的分值在500左右,只有赔率为4的兔子在400左右。保持压8、7、4版型的原因是,该版型出彩金动物的几率比较大,尤其玩得多的人知道,出高分彩金兔子,一般在4倍和5倍上居多,况且,即使中了4倍赔率,也不亏分;
  根据正常的机器一般出大小机率的比例是6:1,所以这种方法一直压,自己的分能不断向上涨,即使出一、两把熊猫或者狮子,也很快通过几把猴子、兔子赚回来,而且经常会遇到彩金动物。其中的乐趣要自己去切身体会。
  600分的平均压法同以上原理,只不过是选择了两台同时压,比如这台13分压够了,另一台可以不压,另一台5分压满,不足的这台补足,只要将600分平均分配下去就OK。这个方法其实是和400平均压法结合的,在连续出了熊猫、狮子后选择600分压法,在可能出现熊猫、狮子的迹象时,选择400分压法,当然,如果你缺乏观察的能力,那么不妨一直用400分的压法。

QQ690907862

#41


经过昨天一下午的研究,问题已经得到彻底解决。我将另发文详细说明。
感谢大家的关注和帮助。

#42


mark

#43


study

#44


mark

#45


#46


学习,做记录

#47


学习,留个脚印

#48


C#调用PB ?

#49


C#调用pb提供的api

#1


然后我市这样声名的

函数
 [DllImport("pborc90.dll", EntryPoint = "PBORCA_LibraryDirectory")]
        public static extern int EntryList(uint sessionId, string libName, StringBuilder libComents, int comentSize, dele_test treatFunc, uint UserData); 
    
两个结构体     
 [StructLayout(LayoutKind.Sequential)]
    public struct ORCA_UserDataInfo
    {
      //  public char[] entryInfo; // Buffer for entry info
        public uint dwCallCount; // # of entries in lib
        public uint dwBufferSize; // size of buffer
        public uint dwBufferOffset; // current offset in buffer
    }
    [StructLayout(LayoutKind.Sequential)]
   public struct PBORCA_DIRENTRY
    {
     public   char[] szComments; // Buffer for entry info
        public int lCreateTime; // # of entries in lib
        public int lEntrySize; // size of buffer
        public string lpszEntryName; // current offset in buffer
        public uint otEntryType;

    }

委托
    public delegate void dele_test(PBORCA_DIRENTRY entryInfo, uint udInfo);

调用过程
uint sessionId;
                sessionId = OpenSession();
                int returnValue;
            StringBuilder sbComment=new StringBuilder (5000);
            dele_test dele_t1 = new dele_test(treatEntryInfo);
            ORCA_UserDataInfo udi=new ORCA_UserDataInfo ();
                   PBORCA_DIRENTRY pd = new PBORCA_DIRENTRY();
           returnValue= EntryList(sessionId, "c:\\ihatepb.pbl", sbComment, sbComment.Length, dele_t1,0);

结果出来各种奇怪的错误,有什么数组与元数据不符,或者数组类型错误,或者内存不能写等等。
总之就是数据类型对照有错误。
请各位老师不吝赐教,谢谢


#2


回调函数在C#里要定义成委托类型

#3


[StructLayout(LayoutKind.Sequential)] 
    public struct ORCA_UserDataInfo 
    { 
      //  public char[] entryInfo; // Buffer for entry info 
        public uint dwCallCount; // # of entries in lib 
        public uint dwBufferSize; // size of buffer 
        public uint dwBufferOffset; // current offset in buffer 
    } 
    [StructLayout(LayoutKind.Sequential)] 
  public struct PBORCA_DIRENTRY 
    { 
    public  char[] szComments; // Buffer for entry info 
        public int lCreateTime; // # of entries in lib 
        public int lEntrySize; // size of buffer 
        public string lpszEntryName; // current offset in buffer 
        public uint otEntryType; 

    } 
=====================
这两个结构里面的 char[]  都要定义长度

#4


public static extern int EntryList(uint sessionId, string libName, StringBuilder libComents, int comentSize, dele_test treatFunc, uint UserData); 

这里的 LPSTR 你知道用 StringBuilder

那public struct PBORCA_DIRENTRY 这里的public string lpszEntryName;为啥不用

#5


C\C++ 中的 char是类型一个字节

C# 中的 char类型,所以转换的时候要用byte取代C\C++中的char

大概是这样:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)]
public  byte[] szComments; // Buffer for entry info 

参考EnumWindows标准API回调的使用:

using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[DllImport("user32.dll")]
public static extern int EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);

public static bool EnumFunc(IntPtr hwnd, int lParam)
{
    Console.WriteLine("Window handle is " + hwnd);
    return true;
}

private void button1_Click(object sender, EventArgs e)
{
    EnumWindows(EnumFunc, 0);
}

#6


C# 中的 char类型两个字节。

#7


十分感谢大家的积极回复。
现就大家提出的方法解释一下
 eglic 
你提出的问题,第一,我在结构体里面定义char[]entry=new char[50];地时候,编译提示结构体中不允许初始化(我是英文vs,可能翻译的不准确)
第二,我第一次用stringbuilder,但是运行时提示stringbuilder 不能用在结构体中,让我用初始化的string代替,我想string肯定不行了,那就只好用char凑合

zswang 我先回复,然后再详细看你的例子。
感谢各位的帮助

#8


提出的问题,第一,我在结构体里面定义char[]entry=new char[50];地时候,编译提示结构体中不允许初始化(我是英文vs,可能翻译的不准确) 

用Marshal....

  public struct PBORCA_DIRENTRY 
    { 
    [MarshalAs(SizeConst=50)]
    public  char[] szComments; // Buffer for entry info 
        public int lCreateTime; // # of entries in lib 
        public int lEntrySize; // size of buffer 
        public string lpszEntryName; // current offset in buffer 
        public uint otEntryType; 

    } 

#9


using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[DllImport("user32.dll")]
public static extern int EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);

public static bool EnumFunc(IntPtr hwnd, int lParam)
{
    Console.WriteLine("Window handle is " + hwnd);
    return true;
}

private void button1_Click(object sender, EventArgs e)
{
    EnumWindows(EnumFunc, 0);
}

这段代码我基本看懂了,但是有几个地方跟我预期的有出入
1声名的时候声名的是一个委托WNDENUMPROC ,传递的时候是传函数名。
我声明的时候也是一个委托,但是传的时候使用的是委托的实例。不知道我这种有没有问题
2intptr字面意思应该是整数指针的意思,那么他跟ulong是不是可以互换?有什么特殊性?
3 我觉得关键是那几个struct怎么声明和调用。

再次感谢您。

#10


int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 

从函数原型的字面意思很难猜出 LPSTR lpszLibName, LPSTR lpszLibComments
这两个是传入还是传出了

传入用 string就可以了
传出用 StringBuilder

PBORCA_DIRENTRY这个结构里面的 LPSTR lpszEntryName; 
这个可能会有点麻烦,这个应该是传出一个字符串
如果文档中没有定义的话,那这个应该是传出一个指针

你可以尝试定义为 IntPtr,然后用
Marshal.PtrToStringAnsi 
或者 PtrToStringAuto 或者 PtrToStringBSTR  或者 PtrToStringUni 转换一下

#11


eglic 

Error 2 'System.Runtime.InteropServices.MarshalAsAttribute' does not contain a constructor that takes '0' arguments E:\My Document\Visual Studio 2008\Projects\PBORCATry\PBORCATry\Program.cs 160 10 PBORCATry

#12


引用 11 楼 phyloinker 的回复:
eglic 

Error 2 'System.Runtime.InteropServices.MarshalAsAttribute' does not contain a constructor that takes '0' arguments E:\My Document\Visual Studio 2008\Projects\PBORCATry\PBORCATry\Program.cs 160 10 PBORCATry 


楼上已经有人给出完整的了

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)] 

#13


int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 

从函数原型的字面意思很难猜出 LPSTR lpszLibName, LPSTR lpszLibComments 
这两个是传入还是传出了 

hORCASession,传入 lpszlibName,lpszLibComments 传出 iCmntsBuffSize 传入 pListProc回调函数
pUserData 

Pointer to user data to be passed to the PBORCA_LibraryDirectory callback function 
The user data typically includes the buffer or a pointer to the buffer in which the callback function formats the directory information as well as information about the size of the buffer 

我英文不好,硬是没看到这个字段时干吗用的。感觉上应该是一个传出的。用来保存directory infomation的。

#14


楼上各位的指教我会好好消化
现在还有一个问题
就是

int PBORCA_LibraryDirectory ( HPBORCA hORCASession, LPSTR lpszLibName, LPSTR lpszLibComments, int iCmntsBuffSize, PBORCA_LISTPROC pListProc, LPVOID pUserData ); 
 LPVOID pUserData 这个东西我声明的时候市声明称
uint UserData

还是我自定义的结构体类型
ORCA_UserDataInfo UserData?

还有那个回调函数的原型
typedef void (FAR PASCAL *PBORCA_LISTPROC) ( PPBORCA_DIRENTRY, LPVOID ); 
PPBORCA_DIRENTRY  //定义的结构体

LPVOID //刚才那个ORCA_UserDataInfo结构体
 
这两个参数我在定义的时候是定义成


 public delegate void dele_test(PBORCA_DIRENTRY entryInfo, ORCA_UserDataInfo udInfo);
还是
 public delegate void dele_test(uint entryInfo, uint udInfo);
或者是
 public delegate void dele_test(intptr entryInfo, intptr udInfo);

第一次正儿八经的写API的应用,请包涵

#15


哈哈,按照大家的指示
char改撑byte
传委托的实例改成传函数名
还有那个marshell
虽然结果还不正确,但是起码不抱错了。十分感谢各位指导!尤其感谢eglic  

#16


声明的时候尽量接近原型

用IntPtr是万不得已的情况,遇上了变态的API。。。

#17


这个只能你自己多实验了,反正就那么几种办法,一个不行换一个再试试

#18


引用 5 楼 zswang 的回复:
C\C++ 中的 char是类型一个字节 

C# 中的 char类型,所以转换的时候要用byte取代C\C++中的char 

大概是这样: 

[MarshalAs(UnmanagedType.ByValArray, SizeConst = PBORCA_MAXCOMMENT + 1)] 
public byte[] szComments; // Buffer for entry info 

参考EnumWindows标准API回调的使用: 

C# code
using System.Runtime.InteropServices;

public delegate bool WNDENUMPROC(IntPtr hwnd, int lParam);

[Dll…



帮顶

#19


运行时不抱错了,但是传给回调函数的都是空值………………
痛苦啊!
知识到用时方恨少

#20


哇   高手!!!!

#21


而且倒了回调函数运行完毕之后,没有返回主调用那个地方继续运行,直接停在那里了………………是不是关于回调我还有什么没注意的…………

#22


typedef struct ORCA_UserDataInfo
{
LPSTR lpszBuffer; // Buffer for entry info
DWORD dwCallCount; // # of entries in lib
DWORD dwBufferSize; // size of buffer
DWORD dwBufferOffset; // current offset in buffer
} ORCA_USERDATAINFO, FAR *PORCA_USERDATAINFO;

这是例子中的结构体的定义
我转成了
 [StructLayout(LayoutKind.Sequential)]
    public struct ORCA_UserDataInfo
    {

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)] 
        public byte[] entryInfo; // Buffer for entry info
        public uint dwCallCount; // # of entries in lib
        public uint dwBufferSize; // size of buffer
        public uint dwBufferOffset; // current offset in buffer
    }

结果是我调整那个SizeConst = 200,就会得到不同的结果,有时候是写保护,有时候时空,有时候能有值但是不知道对不对。

这四个成员应该都是输出方向的,是不是要加ref或者out之类的?

#23


原文中是这样的

CHAR szComments[PBORCA_MAXCOMMENT + 1]; 

所以你应该先找到 PBORCA_MAXCOMMENT 这个的定义

#24


坦白的说,我没找到PBORCA_MAXCOMMENT
但是我估计他是指得comment的最大值,我只要把它设置成足够大应该就可以了。

他给了一个例子
ORCA_USERDATAINFO UserDataBuffer;
PORCA_USERDATAINFO lpUserDataBuffer;
CHAR InfoBuffer[60000];
LPSTR pszLibraryName;
CHAR szComments[PBORCA_MAXCOMMENT];

// Set library name
pszLibraryName = "c:\\myapp\\ver1\\datamod.pbl";

// Initialize UserDataBuffer
lpUserDataBuffer = &UserDataBuffer;

lpUserDataBuffer->dwCallCount = 0;
lpUserDataBuffer->dwBufferOffset = 0;
lpUserDataBuffer->dwBufferSize = 60000;
lpUserDataBuffer->lpszBuffer = (LPSTR) InfoBuffer;

// Initialize all of InfoBuffer to 0
memset(lpUserDataBuffer->lpszBuffer,
0x00, (size_t) lpUserDataBuffer->dwBufferSize);

// Get the proc address of callback function
lpListProc = MakeProcInstance(
(FARPROC)LibraryList, hInst);

// Call ORCA function
lpORCA_Info->lReturnCode = PBORCA_LibraryDirectory(
lpORCA_Info->hORCASession, pszLibraryName,
(LPSTR) szComments, PBORCA_MAXCOMMENT,
(PBORCA_LISTPROC) lpListProc, lpUserDataBuffer);

//Release the proc instance resource
FreeProcInstance(lpListProc);


不过C语言的我看得不是很明白。但是我注意到
lpUserDataBuffer->lpszBuffer = (LPSTR) InfoBuffer;
也就是说结构体里面的第一个成员
LPSTR lpszBuffer; // Buffer for entry info 

实际上应该是一个指针,这样的话,我是不时就不应该定义成byte了?而应该定义成ulong或者inptr?
然后把它赋值到一个byte[]的首地址?
但是怎么取byte[]的首地址呢?

#25


PBORCA_MAXCOMMENT 是第一个结构体的,我刚才说的是第二个结构体,所以不牵扯PBORCA_MAXCOMMENT

#26


结构是一个固定长度的,所以你不可以将那个字符串设置的太长或者太短

你先找到第二个结构体的定义再说

#27


疯掉了。结贴送分,你不忙的话加我QQ165711698

#28


http://manuals.sybase.com/onlinebooks/group-pb/adt0650e/orca/@Generic__BookTextView/86;pt=45

在这里找到ORCA_USERDATAINFO的定义

typedef struct ORCA_UserDataInfo {
LPSTR lpszBuffer; // Buffer to store data 
DWORD dwCallCount; // # of messages in buffer 
DWORD dwBufferSize; // size of buffer 
DWORD dwBufferOffset; // current offset in buffer 
} ORCA_USERDATAINFO, FAR *PORCA_USERDATAINFO;

看来他是返回一个指针,你用IntPtr试试

然后在返回里面,用 string message=Marshal.PtrToStringANSI(ORCA_UserDataInfo.lpszBuffer,ORCA_UserDataInfo.dwBufferSize);

#29


哦,错了…………
上面不对,你可能需要用到 unsafe …………

它是预先定义一个buffer
然后把buffer的指针传过去


。。。。麻烦大了

#30


饿,学习了

#31


友情帮顶

#32


.......突然发现居然有幸得到版主垂青…………受宠若惊阿。
虽然已经结贴,其实还有有一些问题没解决。写出来供大家参考学习

 

#33


回调函数中结构体的原型
typedef struct pborca_direntry {
 TCHAR szComments[PBORCA_MAXCOMMENT + 1];
 LONG lCreateTime; 
LONG lEntrySize;
 LPSTR lpszEntryName; 
PBORCA_TYPE otEntryType;}
 PBORCA_DIRENTRY, FAR *PPBORCA_DIRENTRY;

对于里面的TCHAR和LPSTR的处理问题。
eglic 认为TCHAR可以直接用char[]也就是
 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public char[] szComments; // Buffer for entry info 
另外对结构体中的LPSTR lpszEntryName;
因为结构体中不允许使用stringBuilder
eglic 建议使用intPTR
但是不知道如何在回调函数中取得这个ptr指针指向地址的内容,现在还正在研究中。

欢迎各位继续发表高见,分当然就没有了。。。。

#34


LZ可以参考下我以前发的关于C#回调的帖子,虽然我的DELPHI与C#的,但相信还是对你有帮助的。
另外:你也许要补充下基础知识,就是关于函数DLL调用的标准,内存对不齐,是不可能调用正确的,参数类型上REF与IN、OUT是有区别的。

#35


回楼上,不是也许,是一定,初学者,见笑。
内存对齐的问题刚看了点介绍,正在准备学以致用
正在拜读您的大作。

#36


.NET Framework 开发人员指南  
如何:实现回调函数  

以下过程和示例演示托管应用程序如何使用平台调用来输出本地计算机上每个窗口的句柄值。尤其是,该过程和示例将使用 EnumWindows 函数来逐步浏览窗口列表,并使用一个托管回调函数(名为 CallBack)来输出窗口句柄的值。

实现回调函数

1. 开始实现之前,先查看 EnumWindows 函数的签名。EnumWindows 具有以下签名:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)

表示此函数需要回调的线索之一是存在 lpEnumFunc 参数。如果参数采用指向回调函数的指针,其名称中通常会有 lp(长指针)前缀与 Func 后缀的组合。有关 Win32 函数的文档,请参见 Microsoft Platform SDK。 

2. 创建托管回调函数。该示例声明一个名为 CallBack 的委托类型,此委托类型采用两个参数:hwnd 和 lparam。第一个参数是窗口的句柄;第二个参数由应用程序定义。在此版本中,这两个参数都必须是整数。
回调函数通常会返回非零值来表示成功,返回零来表示失败。本示例将返回值显式设置为 true,以继续进行枚举。 

3. 创建一个委托,并将其作为参数传递给 EnumWindows 函数。平台调用会自动将委托转换为常见的回调格式。

4. 确保在回调函数完成其工作之前,垃圾回收器不会回收委托。如果委托作为参数进行传递,或者所包含的委托作为结构中的字段进行传递,则该委托在调用期间不会被回收。因此,正如下面的枚举示例所示,回调函数会在调用返回前完成其工作,而无需托管调用方执行额外的操作。 
然而,如果可以在调用返回后调用回调函数,则托管调用方必须采取相应的措施来确保委托在回调函数完成其工作之前不会被回收。有关防止垃圾回收的详细信息,请参见用平台调用进行 Interop 封送处理。 

示例
Imports System
Imports System.Runtime.InteropServices

Public Delegate Function CallBack( _
hwnd As Integer, lParam As Integer) As Boolean

Public Class EnumReportApp

    Declare Function EnumWindows Lib "user32" ( _
       x As CallBack, y As Integer) As Integer

    Public Shared Sub Main()
        EnumWindows(AddressOf EnumReportApp.Report, 0)
    End Sub 'Main

    Public Shared Function Report(hwnd As Integer, lParam As Integer) _
    As Boolean
        Console.Write("Window handle is ")
        Console.WriteLine(hwnd)
        Return True
    End Function 'Report
End Class 'EnumReportApp

using System;
using System.Runtime.InteropServices;

public delegate bool CallBack(int hwnd, int lParam);

public class EnumReportApp {

    [DllImport("user32")]
    public static extern int EnumWindows(CallBack x, int y); 

    public static void Main() 
    {
        CallBack myCallBack = new CallBack(EnumReportApp.Report);
        EnumWindows(myCallBack, 0);
    }

   public static bool Report(int hwnd, int lParam) { 
        Console.Write("Window handle is ");
        Console.WriteLine(hwnd);
        return true;
    }
}

using namespace System::Runtime::InteropServices;

// A delegate type.
__delegate bool CallBack(int hwnd, int lParam);

// Managed type with the method to call.
__gc class EnumReport 
{
// Report the window handle.
public:
    bool Report(int hwnd, int lParam) {
       Console::Write(L"Window handle is ");
       Console::WriteLine(hwnd);
       return true;
   }
};

[DllImport("user32")] 
extern "C" int EnumWindows(CallBack* x, int y); 

void main(void) { 
    EnumReport* er = new EnumReport;
    CallBack* myCallBack = new CallBack(er, &EnumReport::Report);
    EnumWindows(myCallBack, 0); 
}

#37


该回复于2008-11-06 04:01:51被版主删除

#38


经过peid分析,该dll为VC++连接器版本5.0

经查询vc默认内存对其模为8,枚举类型为4字节
那么我这样声明

 [StructLayout(LayoutKind.Sequential,Pack =8)]
        public struct PBORCA_DIRENTRY
        {
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public char[] szComments; // 原型 TCHAR      szComments[PBORCA_MAXCOMMENT + 1];
                                       //PBORCA_MAXCOMMENT =255
                                       
            public int lCreateTime; // 原型 LONG            lCreateTime;
            public int lEntrySize; // 原型 LONG            lEntrySize; 
            public IntPtr lpszEntryName; // 原型  LPTSTR       lpszEntryName;                   

            public  UInt32 otEntryType;//原型枚举类型

        }

但是结果依然不正确,请各位指正!

#39


该回复于2008-11-06 04:03:00被版主删除

#40


      奔驰宝马连线,动物转盘,水果机破解QQ690907862

技术一:
  适用于所有的狮子王国系列、彩金狮王系列、闪电王系列、飓风系列等。
  该技术在一年多前,曾有人向我请教过,我当时只是告诉他用400分或600分的平均压法。但具体的细节仍然做了保留,结果在后来网上流传的一个彩金狮王的技术压法就是400分或600分的平均压。甚至有人还拿这个来卖钱。
  结果显得非常可笑,因为所有拿到这个技术的人,都会陷入一个莫名的尴尬,就是比如投资400分,那么8分压50,5分压80分,出分都是400分,结果却发现400或600平均压法,总会压不完所有的动物,而导致每把亏分,跑什么都亏分,就算是放弃其中一或两种动物不压,每把也不能赚分,甚至跑到自己不压的那个动物,更是亏得血本无归。
  其实,400分的平均压法的真正原理是投入400分,每把都能赚100分左右。
  要彻底明白这个技术,你还应该知道的是:
  1、 这类连线机一般是最大46倍,最小4倍的系列。因为机器始终要保持正常的赢利,所以正常的机器一般出大小机率的比例是6:1左右,黑一点的老板一般把难度调高,难度调高后的大小比例一般在7或8:1,这里的“大”指的是出狮子或者熊猫的机率,“小”指的是出猴子和兔子的机率。
  2、 这类连线机只可能有3种版型,即兔子的倍数分别为:8、7、4和8、6、5以及5、6、7。
  
  所以针对不同的版型我们的压分方法应该如下:
  8、6、5版型:
  狮子的赔率分别为:46、35、28,熊猫的赔率为:23、17、14
  猴子的赔率为:13、10、8 兔子的赔率为:8、6、5
  于是压分的方法为(400分平均压):
  13猴子压39分:13X39==507 10猴子压50分:10X50==500
  8猴子和兔子压63分:8X63==504 6兔子压84分:6X84==504
  5的兔子压99分:5X99==495
  总压分为:39+50+63+63+84+99==398分
  
  7、6、5版型:
  狮子的赔率分别为:40、35、28,熊猫的赔率为:20、17、14
  猴子的赔率为:11、10、8 兔子的赔率为:7、6、5
  于是压分的方法为(400分平均压):
  11猴子压46分:11X46==506 10猴子压50分:10X50==500
  8猴子压63分:8X63==504 7的兔子压72分:7X72==504
  6兔子压84分:6X84==504 5的兔子压99分:5X99==495
  总压分为:46+50+63+72+84+99==414分
  
  8、7、4版型:
  狮子的赔率分别为:46、40、25,熊猫的赔率为:23、17、12
  猴子的赔率为:13、11、7 兔子的赔率为:8、7、4
  于是压分的方法为(400分平均压):
  13猴子压39分:13X39==507 11猴子压46分:11X46==506
  8猴子压63分:8X63==504 7的猴子和兔子压72分:7X72==504
  4的兔子压99分:4X99==396
  总压分为:39+45+63+72+72+99==390分
  
  从上面3种压分方法可以看出,每次投入的分值在400分左右,而出来的分值在500左右,只有赔率为4的兔子在400左右。保持压8、7、4版型的原因是,该版型出彩金动物的几率比较大,尤其玩得多的人知道,出高分彩金兔子,一般在4倍和5倍上居多,况且,即使中了4倍赔率,也不亏分;
  根据正常的机器一般出大小机率的比例是6:1,所以这种方法一直压,自己的分能不断向上涨,即使出一、两把熊猫或者狮子,也很快通过几把猴子、兔子赚回来,而且经常会遇到彩金动物。其中的乐趣要自己去切身体会。
  600分的平均压法同以上原理,只不过是选择了两台同时压,比如这台13分压够了,另一台可以不压,另一台5分压满,不足的这台补足,只要将600分平均分配下去就OK。这个方法其实是和400平均压法结合的,在连续出了熊猫、狮子后选择600分压法,在可能出现熊猫、狮子的迹象时,选择400分压法,当然,如果你缺乏观察的能力,那么不妨一直用400分的压法。

QQ690907862

#41


经过昨天一下午的研究,问题已经得到彻底解决。我将另发文详细说明。
感谢大家的关注和帮助。

#42


mark

#43


study

#44


mark

#45


#46


学习,做记录

#47


学习,留个脚印

#48


C#调用PB ?

#49


C#调用pb提供的api