Вызов АПИ-функции
От: _FRED_ Черногория
Дата: 08.12.04 22:10
Оценка:
Прошу ткнуть меня в RTFM, где сказано, почему следующее работает не так, как мне надо
Имеем С-длл в которой объявлена следующая функция:
extern "C" bool __stdcall Test()
{
  return true;
}


В Басике делаем так:
Private Declare Function Test1 Lib "MyLib.dll" Alias "_Test@0" () As Boolean

Private Function MyTest1() As Boolean
  Dim b As Boolean
  b = Test1()
  Debug.Print "Test1[1]: " & b
  b = Not b
  Debug.Print "Test1[2]: " & b
End Function

Private Function Test2() As Boolean
  Test2 = True
End Function

Private Function MyTest2() As Boolean
  Dim b As Boolean
  b = Test2()
  Debug.Print "Test2[1]: " & b
  b = Not Test2()
  Debug.Print "Test2[2]: " & b
End Function

Private Sub MyTest()
  Call MyTest1
  Call MyTest2
End Sub


И что же видим в Immediate после выполнения MyTest()?
Test1[1]: True
Test1[2]: True
Test2[1]: True
Test2[2]: False


И это не смотря на то, что [ здесь ]
Declare Statement

[Public | Private] Declare Function name Lib "libname" [Alias "aliasname"] [([arglist])] [As type]

The Declare statement syntax has these parts:
[skipped]
type    Optional. Data type of the value returned by a Function procedure; 
        may be Byte, Boolean, Integer, Long, Currency, Single, Double, 
        Decimal (not currently supported), Date, String (variable length only), 
        or Variant, a user-defined type, or an object type.

и [ здесь ]
Not Operator

Used to perform logical negation on an expression.

и
Remarks
The following table illustrates how result is determined:
If expression is Then result is 
True  False 
False True 
Null  Null


Догадываюсь, что на самом деле он поступает так:
In addition, the Not operator inverts the bit values of any variable and sets the corresponding bit in result according to the following table:
If bit in expression is Then bit in result is 
0 1 
1 0


Но почему?

Что делать — понятно — задекларировать функуцию как возвращающую Long и сравнивать с нулём, но всё же...
Help will always be given at Hogwarts to those who ask for it.
Re: Вызов АПИ-функции
От: rockandroll Казахстан  
Дата: 09.12.04 04:25
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Прошу ткнуть меня в RTFM, где сказано, почему следующее работает не так, как мне надо


Может потому что в C++

Microsoft Specific

In Visual C++4.2, the Standard C++ header files contained a typedef that equated bool with int. In Visual C++ 5.0 and later, bool is implemented as a built-in type with a size of 1 byte. That means that for Visual C++ 4.2, a call of sizeof(bool) yields 4, while in Visual C++ 5.0 and later, the same call yields 1. This can cause memory corruption problems if you have defined structure members of type bool in Visual C++ 4.2 and are mixing object files (OBJ) and/or DLLs built with the 4.2 and 5.0 or later compilers.


А в Basic:

Boolean variables are stored as 16-bit (2-byte) numbers, but they can only be True or False. Boolean variables display as either True or False (when Print is used) or #TRUE# or #FALSE# (when Write # is used). Use the keywords True and False to assign one of the two states to Boolean variables.

When other numeric types are converted to Boolean values, 0 becomes False and all other values become True. When Boolean values are converted to other data types, False becomes 0 and True becomes -1.


Т.е. в C++ — 1 байт, в Basic — 2 байта, IMHO конечно.
... << RSDN@Home 1.1.4 >>
Re[2]: Вызов АПИ-функции
От: _FRED_ Черногория
Дата: 09.12.04 04:40
Оценка:
Здравствуйте, rockandroll, Вы писали:
_FR>>Прошу ткнуть меня в RTFM, где сказано, почему следующее работает не так, как мне надо

[skipped]

R>

R>Boolean variables are stored as 16-bit (2-byte) numbers, but they can only be True or False. Boolean variables display as either True or False (when Print is used) or #TRUE# or #FALSE# (when Write # is used). Use the keywords True and False to assign one of the two states to Boolean variables.

R>When other numeric types are converted to Boolean values, 0 becomes False and all other values become True. When Boolean values are converted to other data types, False becomes 0 and True becomes -1.

R>Т.е. в C++ — 1 байт, в Basic — 2 байта, IMHO конечно.

Вот из выделенного я делаю вывод, что
  Dim b As Boolean
  b = 10
  Dim l As Long
  l = b
  Debug.Assert l = -1

Будет всегда работать на ура, и это подтверждается.

При вызове из АПИ почему-то что-то не так. Если сделать этак:
Private Declare Function Test1 Lib "HAudio.dll" Alias "_Test@0" () As Long 'Для той-же функции в длл, возвращающей bool

Private Function MyTest1() As Boolean
  Dim b As Long
  b = Test1()
  Debug.Print "Test1: " & b
End Function

Private Sub Form_Load()
  Call MyTest1
End Sub


Получим:
Test1: -858993663


И кто прав, кто виноват
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Вызов АПИ-функции
От: rockandroll Казахстан  
Дата: 09.12.04 05:47
Оценка: 18 (1)
Здравствуйте, _FRED_, Вы писали:

_FR>При вызове из АПИ почему-то что-то не так. Если сделать этак:

_FR>
_FR>Private Declare Function Test1 Lib "HAudio.dll" Alias "_Test@0" () As Long 'Для той-же функции в длл, возвращающей bool

_FR>Private Function MyTest1() As Boolean
_FR>  Dim b As Long
_FR>  b = Test1()
_FR>  Debug.Print "Test1: " & b
_FR>End Function

_FR>Private Sub Form_Load()
_FR>  Call MyTest1
_FR>End Sub
_FR>


_FR>Получим:

_FR>
Test1: -858993663


_FR>И кто прав, кто виноват


Как я и говорил — это все из-за несоответствия типов возвращаемых результатов:
Long — 4 байта
bool в C++ — 1 байт.

Поменяй импорт в VB так:

Private Declare Function Test1 Lib "HAudio.dll" Alias "_Test@0" () As Byte

Получишь 1.
... << RSDN@Home 1.1.4 >>
Re[4]: Вызов АПИ-функции
От: _FRED_ Черногория
Дата: 09.12.04 05:51
Оценка:
Здравствуйте, rockandroll, Вы писали:

R>Как я и говорил — это все из-за несоответствия типов возвращаемых результатов:

R>Long — 4 байта
R>bool в C++ — 1 байт.
R>Поменяй импорт в VB так:
R>Private Declare Function Test1 Lib "HAudio.dll" Alias "_Test@0" () As Byte
R>Получишь 1.

Ура! Теперь,наконец, дошло, почему это так происходит
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Вызов АПИ-функции
От: hermit. Россия  
Дата: 09.12.04 07:53
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

_FR>Ура! Теперь,наконец, дошло, почему это так происходит


Да. И объяви наконец def файл с
EXPORT
Test

Ато "_Test@0" как-то некузяво смотрится
... << RSDN@Home 1.1.3 stable >>
The darkness around me
Shores of solar sea
Oh how i wish to go down with the sun....
Re[6]: Вызов АПИ-функции
От: Elena_ Россия  
Дата: 09.12.04 08:01
Оценка: 18 (1)
Здравствуйте, hermit., Вы писали:

Daniel Appleman Visual Basic Programmer’s Guide to the Win32 API

Chapter 3

Dll Parameters

Booleans

Both Visual Basic and C define a Boolean FALSE as zero, and all nonzero values as TRUE. It is important to note, however, that in C programming the value for TRUE is typically 1, whereas in Visual Basic the value of TRUE is typically –1. This difference can lead to confusion in cases where a programmer makes assumptions about the value of the TRUE condition. For example, to determine if a window is visible using the IsWindowVisible() API, use:


If IsWindowVisible(hWnd%) then .... '
or
If IsWindowVisible(hWnd%)<>Ш then .... '
The following won’t work:
If IsWindowVisible(hWnd%) = -1 then ....
or
If Not IsWindowVisible(hWnd%) then


The latter examples may not work because Windows does not specify that IsWindowVisible will return –1 when a window is visible, only that the result will be nonzero. If IsWindowVisible returns the value 1, you have the incredible situation in Visual Basic where:


if IsWindowVisible And (Not IsWindowVisible) Then
' This code will execute!!! The condition is True


For those who are curious, the reason this difference exists relates to differences between the C and C++ languages and Visual Basic. C and C++ include both logical and Boolean operations. Consider the “Not” operation (used to determine if something is Not true). The logical NOT operation in C is indicated by the ~ symbol in front of a variable name. The Boolean NOT operation is indicated by the ! symbol.
~1 is &HFFFE—both values that are nonzero and logically TRUE.

But !1 is 0, and !&HFFFF is 0 as well. Since logical operations would always be used on results, it does not matter what the value of TRUE is, as long as it is nonzero.
Visual Basic does not have a Boolean operator. The only way for NOT TRUE to be FALSE is if TRUE is always –1 and FALSE is always 0. Purists might argue that this means that all values other than 0 and –1 are undefined with regard to Boolean operations (since it becomes possible for NOT TRUE to be TRUE—a Boolean impossibility). Pragmatists such as I will be satisfied with a warning: Be careful how you use Boolean results from API functions.

Пользователь — друг программиста!
Re: Вызов АПИ-функции
От: Vi2 Удмуртия http://www.adem.ru
Дата: 09.12.04 10:03
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>В Басике делаем так:

_FR>Private Declare Function Test1 Lib "MyLib.dll" Alias "_Test@0" () As Boolean

Для такой спецификации (VB-шный Boolean) функция на С должна быть такой:
extern "C" VARIANT_BOOL __stdcall Test()
{
  return VARIANT_TRUE; // VARIANT_TRUE вместо true и VARIANT_FALSE вместо false
}
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.