Прошу ткнуть меня в 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 и сравнивать с нулём, но всё же...
Здравствуйте, _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 >>
Здравствуйте, 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
И кто прав, кто виноват
Здравствуйте, _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 >>
Здравствуйте, 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.
Ура! Теперь,наконец, дошло, почему это так происходит
Здравствуйте, _FRED_, Вы писали:
_FR>Ура! Теперь,наконец, дошло, почему это так происходит
Да. И объяви наконец def файл с
EXPORT
Test
Ато "_Test@0" как-то некузяво смотрится
... << RSDN@Home 1.1.3 stable >>
Здравствуйте, 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.
Здравствуйте, _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
}