Declaring SCardStatus function causes the error: "couldn't find function symbol in library"
The Code is as follows:
Cu.import('resource://gre/modules/ctypes.jsm');
var is64bit = ctypes.voidptr_t.size == 4 ? false : true;
var ifdef_UNICODE = true;
var TYPES = {
ABI: is64bit ? ctypes.default_abi : ctypes.winapi_abi,
CHAR: ctypes.char,
DWORD: ctypes.uint32_t,
LONG: ctypes.long,
LPCVOID: ctypes.voidptr_t,
ULONG_PTR: is64bit ? ctypes.uint64_t : ctypes.unsigned_long,
WCHAR: ctypes.jschar,
};
TYPES.LPSTR = TYPES.CHAR.ptr;
TYPES.LPDWORD = TYPES.DWORD.ptr;
TYPES.LPWSTR = TYPES.WCHAR.ptr;
TYPES.SCARDHANDLE = TYPES.ULONG_PTR;
TYPES.LPBYTE = TYPES.LPSTR;
TYPES.LPTSTR = ifdef_UNICODE ? TYPES.LPWSTR : TYPES.LPSTR;
var cardLib = ctypes.open('Winscard');
var SCardStatus = cardLib.declare('SCardStatus', TYPES.ABI, TYPES.LONG, TYPES.SCARDHANDLE, TYPES.LPTSTR, TYPES.LPDWORD, TYPES.LPDWORD, TYPES.LPDWORD, TYPES.LPBYTE, TYPES.LPDWORD );
I guess that TYPES.LPBYTE is not correct, according to https://msdn.microsoft.com/en-us/library/windows/desktop/aa379803%28v=vs.85%29.aspx , LPBYTE should be a Pointer to a 32-byte buffer that receives the ATR string from the currently inserted card, if available. However I could not fix it, I appreciate any helps in advanced.
In winapi if the functions have two versions, unicode version and ascii verison IF it takes strings. So the docs show this accepts characters, so on the page it shows: SCardStatusW (Unicode) and SCardStatusA (ANSI) so you have to define it like this: var SCardStatus = cardLib.declare(ifdef_UNICODE ? 'SCardStatusW' : 'SCardStatusA', ....
Related
I'm maintaining a project which contains following enum type definition. enum values are used in
a combobox.
Why this enum type is defined in hex like this, for performance improvement?
xxxxx920P3 is actually a negative value -2147483648 and xxxxx920P2 is positive, it causes the conditional code to fail.The next value will be twice bigger as the xxxxx920P3, so any alternative solution for this enum definition rule? thanks.
It is a QT c++ project. Can I define a enum type to ULONGLONG?
enum Version
{
xxxxx = 0x00000000,
xxxxx400 = 0x00000001,
xxxxx401 = 0x00000002,
xxxxx410 = 0x00000004,
xxxxx411 = 0x00000008,
xxxxx412 = 0x00000010,
xxxxx420 = 0x00000020,
xxxxx430 = 0x00000040,
xxxxx431 = 0x00000080,
xxxxx432 = 0x00000100,
xxxxx440 = 0x00000200,
xxxxx500 = 0x00000400,
xxxxx510 = 0x00000800,
xxxxx520 = 0x00001000,
xxxxx521 = 0x00002000,
xxxxx600 = 0x00004000,
xxxxx611 = 0x00008000,
xxxxx620 = 0x00010000,
xxxxx621 = 0x00020000,
xxxxx700 = 0x00040000,
xxxxx910 = 0x00080000,
xxxxx910P5 = 0x00100000,
xxxxx910P6 = 0x00200000,
xxxxx910P11 = 0x00400000,
xxxxx910P12 = 0x00800000,
xxxxx910P13 = 0x01000000,
xxxxx910P14 = 0x02000000,
xxxxx910P15 = 0x04000000,
xxxxx910P16 = 0x08000000,
xxxxx920 = 0x10000000,
xxxxx920P1 = 0x20000000,
xxxxx920P2 = 0x40000000,
xxxxx920P3 = 0x80000000,
};
Versions newVersions = (Version)mComboBox->itemData(inIndex).toUInt();
if ( newVersions < xxxxx500) //now newVersions is a negative value
{
}
else
{
}
In Standard C enumerators have type int and the value must be in range of int. The 0x80000000 is out of range for int, this is a constraint violation that requires a diagnostic.
So what is happening depends on your compiler. The compiler implements an extension of its own devising for enumerators out of range for int. Based on the evidence you posted, the compiler gives that enumerator a value of INT_MIN (a large negative number).
You will have to design your code to take this into account, e.g. have a specific branch of the verstion test for xxxxx920P3.
When an enumeration contains a bunch of one-bit flags it's usually so that they can be combined together, e.g. xxxxx600 | xxxxx700 | xxxxx432 giving the ability to have a single value that represents any sized set of elements.
I've been trying to call Window's CreateProcessA from Pony Language's FFI.
I created both a C and a PonyLang example. The C example works great:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void wmain(void) {
STARTUPINFO info={0};
PROCESS_INFORMATION processInfo={0};
CreateProcessA("calc.exe", 0, 0, 0, 0, 0, 0, 0, &info, &processInfo);
if (status == 0)
printf("%d",GetLastError()); // never hits
}
I put calc.exe in the current directory. This works flawlessly on Windows.
However, my PonyLang implementation keeps on returning a non zero GetLastError:
use "lib:kernel32"
primitive _ProcessAttributes
primitive _ThreadAttributes
primitive _Inherit
primitive _Creation
primitive _Environment
primitive _CurrentDir
primitive _StartupInfo
primitive _ProcessInfo
primitive _HandleIn
primitive _HandleOut
primitive _HandleErr
primitive _Thread
primitive _Process
struct StartupInfo
var cb:I32 = 0
var lpReserved:Pointer[U8] tag= "".cstring()
var lpDesktop:Pointer[U8] tag= "".cstring()
var lpTitle:Pointer[U8] tag= "".cstring()
var dwX:I32 = 0
var dwY:I32 = 0
var dwXSize:I32=0
var dwYSize:I32=0
var dwXCountChars:I32=0
var dwYCountChars:I32=0
var dwFillAttribute:I32=0
var dwFlags:I32=0
var wShowWindow:I16=0
var cbReserved2:I16=0
var lpReserved2:Pointer[U8] tag="".cstring()
var hStdInput:Pointer[_HandleIn] = Pointer[_HandleIn]
var hStdOutput:Pointer[_HandleOut]= Pointer[_HandleOut]
var hStdError:Pointer[_HandleErr]= Pointer[_HandleErr]
struct ProcessInfo
var hProcess:Pointer[_Process] = Pointer[_Process]
var hThread:Pointer[_Thread] = Pointer[_Thread]
var dwProcessId:I32 = 0
var dwThreadId:I32 = 0
//var si:StartupInfo = StartupInfo
actor Main
new create(env: Env) =>
var si: StartupInfo = StartupInfo
var pi: ProcessInfo = ProcessInfo
var inherit:I8 = 0
var creation:I32 = 0
var one:I32 = 0
var two:I32 = 0
var three:I32 = 0
var four:I32 = 0
var z:I32 = 0
var p = #CreateProcessA[I8]("calc.exe",
z,
one,
two,
inherit,
creation,
three,
four,
addressof si,
addressof pi)
if p == 0 then
var err = #GetLastError[I32]() // hits this every time.
env.out.print("Last Error: " + err.string())
end
So the above code compiles for PonyLang, but GetLastError most of the time returns 2. Sometimes GetLastError returns 123. Other times it returns 998?
It all seems odd that the error code is different sometimes. Those codes all mean that there is some issue with file access?
Calc.exe is in the current directory (same directory as the c example).
Also not only is the Error code different but calc.exe is executed(runs fine) in the C version but not in the PonyLang version. This leads me to believe something is off with my PonyLang ffi setup.
Does anyone know what may be wrong?
The problem is with your use of addressof. When you create a struct object, e.g. with var si = StartupInfo, the underlying type is a pointer to the structure (i.e structs in Pony don't have value semantics). Then when you call CreateProcessA with addressof, you're actually passing a pointer to pointer to the function.
If your C function expects a pointer to a structure, you can simply pass the Pony object without addressof when doing the FFI call.
The type of a Note’s parent or storyOffset property depends on whether the note was obtained from a Text or a Story. Why? How to deal cleanly with this in code working on a Note without knowing where it came from?
The following scripts expose the situation.
// INDESIGN CS6 8.1 VERSION
var doc = app.documents.add();
doc.pages.item(0).textFrames.add();
var story = doc.stories[0];
story.insertionPoints[0].contents = "x";
story.insertionPoints[0].notes.add();
var range = story.texts.itemByRange(story.characters.item(0),
story.characters.item(1));
alert( story .notes[0].parent.constructor.name); // "InsertionPoint"
alert( range .notes[0].parent.constructor.name); // "Array"
alert( story .notes[0].storyOffset.constructor.name); // "InsertionPoint"
alert( range .notes[0].storyOffset.constructor.name); // "Array"
// INCOPY CS6 8.1 VERSION
app.documents.add();
var story = app.selection[0].parentStory;
story.insertionPoints[0].contents = "x";
story.insertionPoints[0].notes.add();
var range = story.texts.itemByRange(story.characters.item(0),
story.characters.item(1));
alert( story .notes[0].parent.constructor.name); // "InsertionPoint"
alert( range .notes[0].parent.constructor.name); // "Array"
alert( story .notes[0].storyOffset.constructor.name); // "InsertionPoint"
alert( range .notes[0].storyOffset.constructor.name); // "Array"
You have to test for every parent constructor that you want to handle. See the documentation for the class hierarchy of a Text object. For example, use a function like this:
var isText = function(text) {
var c = text.constructor;
return c === Paragraph || c === Line || c === Word
|| c === Text || c === TextStyleRange || c === Story
|| c === InsertionPoint || c === TextColumn;
}
isText(story.notes[0].parent) // => true
this is my line of code.
budgetLabel.text = String((budgetLabel.text)!.toInt()! - (budgetItemTextBox.text)!.toInt()!)
the code works, but when I try to input a floating value into the textbox the program crashes. I am assuming the strings need to be converted to a float/double data type. I keep getting errors when i try to do that.
In Swift 2 there are new failable initializers that allow you to do this in more safe way, the Double("") returns an optional in cases like passing in "abc" string the failable initializer will return nil, so then you can use optional-binding to handle it like in the following way:
let s1 = "4.55"
let s2 = "3.15"
if let n1 = Double(s1), let n2 = Double(s2) {
let newString = String( n1 - n2)
print(newString)
}
else {
print("Some string is not a double value")
}
If you're using a version of Swift < 2, then old way was:
var n1 = ("9.99" as NSString).doubleValue // invalid returns 0, not an optional. (not recommended)
// invalid returns an optional value (recommended)
var pi = NSNumberFormatter().numberFromString("3.14")?.doubleValue
Fixed: Added Proper Handling for Optionals
let budgetLabel:UILabel = UILabel()
let budgetItemTextBox:UITextField = UITextField()
budgetLabel.text = ({
var value = ""
if let budgetString = budgetLabel.text, let budgetItemString = budgetItemTextBox.text
{
if let budgetValue = Float(budgetString), let budgetItemValue = Float(budgetItemString)
{
value = String(budgetValue - budgetItemValue)
}
}
return value
})()
You need to be using if let. In swift 2.0 it would look something like this:
if let
budgetString:String = budgetLabel.text,
budgetItemString:String = budgetItemTextBox.text,
budget:Double = Double(budgetString),
budgetItem:Double = Double(budgetItemString) {
budgetLabel.text = String(budget - budgetItem)
} else {
// If a number was not found, what should it do here?
}
I am trying to figure out how to initialize a variable in VBScript to its maximum value.
For example, in C++, I would do something like:
double x = MAX_DOUBLE;
I am not sure how to do this in VBScript.
UPDATE
For now, I have defined the variable myself as constant value in the global scope of the script. I am not sure if this is the most elegant way of doing this. Is there a built-in variable I can use?
Const MAX_DOUBLE = CDbl(1.79769313486232e307)
Const MIN_DOUBLE = CDbl(-1.79769313486232e307)
I've never found the limits described on MSDN to be accurate for many of the VBScript data types. For example, the Currency type gives me an overflow for anything > XXX.5625, even though the docs say it should go to XXX.5808. Same thing for Double. The docs say the max should be 1.79769313486232e308 but that final 2 in the mantissa causes an overflow. These are the values I've used in the past:
Const MIN_BYTE = 0
Const MAX_BYTE = 255
Const MIN_INTEGER = -32768
Const MAX_INTEGER = 32767
Const MIN_LONG = -2147483648
Const MAX_LONG = 2147483647
Const MIN_SINGLE = -3.402823e38
Const MAX_SINGLE = 3.402823e38
Const MIN_DOUBLE = -1.79769313486231e308
Const MAX_DOUBLE = 1.79769313486231e308
Const MIN_CURRENCY = -922337203685477.5625
Const MAX_CURRENCY = 922337203685477.5625
Const MIN_DATE = #100/1/1#
Const MAX_DATE = #9999/12/31#
Because VBScript uses Variants, however, note that you may not get the type you expect when assigning a "max" (or min) value to a variable. For example:
b = MAX_BYTE ' Actually type Integer
s = MAX_SINGLE ' Actually type Double
c = MAX_CURRENCY ' Actually type Double
If you want to ensure you're getting the proper data type in return, you'll need to explicitly cast:
b = CByte(MAX_BYTE) ' Type Byte
s = CSng(MAX_SINGLE) ' Type Single
c = CCur(MAX_CURRENCY) ' Type Currency