I have a procedure with the following signature:
procedure countryExists(iCountryName in varchar2, oCount out integer)
When I run it using OCILIB, I can't get the right value for oCount. If I register it as integer (using OCI_RegisterInt), I get the error:
ORA-03116: invalid buffer length passed to a conversion routine
If I register it as a string, it runs, but OCI_GetString returns a null pointer and OCI_GetInt returns 0 (instead of the expected result 1).
The test code is:
int init = OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT|OCI_ENV_CONTEXT);
OCI_Connection *cn = OCI_ConnectionCreate("mydb", "myuser", "mypass", OCI_SESSION_DEFAULT);
OCI_Statement *st = OCI_StatementCreate(cn);
int resultprepare = OCI_Prepare(st, "call mypackage.countryExists('BRAZIL', :oCount)");
//int registercount = OCI_RegisterString(st, ":oCount", 100);
int registercount= OCI_RegisterInt(st, ":oCount");
int executeresult = OCI_Execute(st);
OCI_Error *err1 = OCI_GetLastError();
const char *error1 = OCI_ErrorGetString(err1);
OCI_Resultset *resultset = OCI_GetResultset(st);
const wchar_t *valstr = OCI_GetString(resultset, 1);
int valint = OCI_GetInt(resultset, 1);
OCI_Error *err2 = OCI_GetLastError();
const char *error2 = OCI_ErrorGetString(err2);
Running the procedure using, for example, PL/SQL Developer works fine.
Is this the right way of calling procedures using OCILIB?
Also note that I'm using the mixed version of the library.
You're not coding in Java....
Here is the right way to do it :
OCI_Connection *cn;
OCI_Statement *st;
int count;
OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT|OCI_ENV_CONTEXT);
cn = OCI_ConnectionCreate("mydb", "myuser", "mypass", OCI_SESSION_DEFAULT);
st = OCI_StatementCreate(cn);
OCI_Prepare(st, "begin mypackage.countryExists('BRAZIL', :oCount); end;");
OCI_BindInt(st, ":oCount", &count);
OCI_Execute(st);
Check the OCILIB documentation and/or manual
Vincent
Related
I am porting the openvr sample to jogl, after we created the binding with jna.
Almost at the end (before rendering the controllers and the tracking base stations), I got stuck trying to translate a char pointer in C to a String in Java.
C++ code here:
//-----------------------------------------------------------------------------
// Purpose: Helper to get a string from a tracked device property and turn it
// into a std::string
//-----------------------------------------------------------------------------
std::string GetTrackedDeviceString( vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop, vr::TrackedPropertyError *peError = NULL )
{
uint32_t unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty( unDevice, prop, NULL, 0, peError );
if( unRequiredBufferLen == 0 )
return "";
char *pchBuffer = new char[ unRequiredBufferLen ];
unRequiredBufferLen = pHmd->GetStringTrackedDeviceProperty( unDevice, prop, pchBuffer, unRequiredBufferLen, peError );
std::string sResult = pchBuffer;
delete [] pchBuffer;
return sResult;
}
GetStringTrackedDeviceProperty here:
/** Returns a string property. If the device index is not valid or the property is not a string type this function will
* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
* null. Strings will generally fit in buffers of k_unTrackingStringSize characters. */
virtual uint32_t GetStringTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0;
Where VR_OUT_STRING() is defined here as:
# define VR_CLANG_ATTR(ATTR)
#define VR_OUT_STRING() VR_CLANG_ATTR( "out_string: ;" )
I have already done something similar where I had to call a function that expect the pointer to an array of TrackedDevicePose_t structures:
private TrackedDevicePose_t.ByReference trackedDevicePosesReference = new TrackedDevicePose_t.ByReference();
public TrackedDevicePose_t[] trackedDevicePose
= (TrackedDevicePose_t[]) trackedDevicePosesReference.toArray(VR.k_unMaxTrackedDeviceCount);
I created first the reference and then from it the actual array.
But here I can't have a class extending the char array..
private String getTrackedDeviceString(IVRSystem hmd, int device, int prop, IntBuffer propError) {
int requiredBufferLen = hmd.GetStringTrackedDeviceProperty.apply(device, prop, Pointer.NULL, 0, propError);
if(requiredBufferLen == 0) {
return "";
}
CharArray.ByReference charArrayReference = new CharArray.ByReference();
char[] cs = charArrayReference.toArray(requiredBufferLen);
return null;
}
Where apply (here) is:
public interface GetStringTrackedDeviceProperty_callback extends Callback {
int apply(int unDeviceIndex, int prop, Pointer pchValue, int unBufferSize, IntBuffer pError);
};
CharArray class, crap attempt here
Any ideas?
I've done some porting of C and C++ code to Java, and while it's probably horribly hacky, the best I've come up with to solve cases where a pointer to an int primitive or a char*/String is needed for a function call, is to create a small wrapper class with a single property, pass that object into the function, change the property as needed, and retrieve the new value after the function call. So something like:
public class StringPointer {
public String value = "";
}
StringPointer pchBuffer = new StringPointer();
unRequiredBufferLen = pHmd.GetStringTrackedDeviceProperty( unDevice, prop, pchBuffer, unRequiredBufferLen, peError );
String sResult = pchBuffer.value;
and inside GetStringTrackedDeviceProperty()
...
pchValue.value = "some string";
...
In this case, you can use a String, since that's what your code is doing with the char* after the function call, but if it actually really needs to be a char[], you can just create char[] pchBuffer = new char[unRequiredBufferLen]; and pass that into the function. It will be just like you were using a char* in C++, and any changes you make inside the array will be visible after the function ends, and you can even do String sResult = new String(pchBuffer);.
When calling WinAPI functions that take callbacks as arguments, there's usually a special parameter to pass some arbitrary data to the callback. In case there's no such thing (e.g. SetWinEventHook) the only way we can understand which of the API calls resulted in the call of the given callback is to have distinct callbacks. When we know all the cases in which the given API is called at compile-time, we can always create a class template with static method and instantiate it with different template arguments in different call sides. That's a hell of a work, and I don't like doing so.
How do I create callback functions at runtime so that they have different function pointers?
I saw a solution (sorry, in Russian) with runtime assembly generation, but it wasn't portable across x86/x64 archtectures.
You can use the closure API of libffi. It allows you to create trampolines each with a different address. I implemented a wrapping class here, though that's not finished yet (only supports int arguments and return type, you can specialize detail::type to support more than just int). A more heavyweight alternative is LLVM, though if you're dealing only with C types, libffi will do the job fine.
I've come up with this solution which should be portable (but I haven't tested it):
#define ID_PATTERN 0x11223344
#define SIZE_OF_BLUEPRINT 128 // needs to be adopted if uniqueCallbackBlueprint is complex...
typedef int (__cdecl * UNIQUE_CALLBACK)(int arg);
/* blueprint for unique callback function */
int uniqueCallbackBlueprint(int arg)
{
int id = ID_PATTERN;
printf("%x: Hello unique callback (arg=%d)...\n", id, arg);
return (id);
}
/* create a new unique callback */
UNIQUE_CALLBACK createUniqueCallback(int id)
{
UNIQUE_CALLBACK result = NULL;
char *pUniqueCallback;
char *pFunction;
int pattern = ID_PATTERN;
char *pPattern;
char *startOfId;
int i;
int patterns = 0;
pUniqueCallback = malloc(SIZE_OF_BLUEPRINT);
if (pUniqueCallback != NULL)
{
pFunction = (char *)uniqueCallbackBlueprint;
#if defined(_DEBUG)
pFunction += 0x256; // variable offset depending on debug information????
#endif /* _DEBUG */
memcpy(pUniqueCallback, pFunction, SIZE_OF_BLUEPRINT);
result = (UNIQUE_CALLBACK)pUniqueCallback;
/* replace ID_PATTERN with requested id */
pPattern = (char *)&pattern;
startOfId = NULL;
for (i = 0; i < SIZE_OF_BLUEPRINT; i++)
{
if (pUniqueCallback[i] == *pPattern)
{
if (pPattern == (char *)&pattern)
startOfId = &(pUniqueCallback[i]);
if (pPattern == ((char *)&pattern) + sizeof(int) - 1)
{
pPattern = (char *)&id;
for (i = 0; i < sizeof(int); i++)
{
*startOfId++ = *pPattern++;
}
patterns++;
break;
}
pPattern++;
}
else
{
pPattern = (char *)&pattern;
startOfId = NULL;
}
}
printf("%d pattern(s) replaced\n", patterns);
if (patterns == 0)
{
free(pUniqueCallback);
result = NULL;
}
}
return (result);
}
Usage is as follows:
int main(void)
{
UNIQUE_CALLBACK callback;
int id;
int i;
id = uniqueCallbackBlueprint(5);
printf(" -> id = %x\n", id);
callback = createUniqueCallback(0x4711);
if (callback != NULL)
{
id = callback(25);
printf(" -> id = %x\n", id);
}
id = uniqueCallbackBlueprint(15);
printf(" -> id = %x\n", id);
getch();
return (0);
}
I've noted an interresting behavior if compiling with debug information (Visual Studio). The address obtained by pFunction = (char *)uniqueCallbackBlueprint; is off by a variable number of bytes. The difference can be obtained using the debugger which displays the correct address. This offset changes from build to build and I assume it has something to do with the debug information? This is no problem for the release build. So maybe this should be put into a library which is build as "release".
Another thing to consider whould be byte alignment of pUniqueCallback which may be an issue. But an alignment of the beginning of the function to 64bit boundaries is not hard to add to this code.
Within pUniqueCallback you can implement anything you want (note to update SIZE_OF_BLUEPRINT so you don't miss the tail of your function). The function is compiled and the generated code is re-used during runtime. The initial value of id is replaced when creating the unique function so the blueprint function can process it.
I am trying to use SAP OLAP BAPI for a very simple task. I want to connect to a SAP BW server, send an MDX query, get the result and disconnect. While I seem to have no problems connecting and disconnecting from the server, sending a query and retrieving results seem to be rather non-trivial tasks that I am seeking help with.
According to the SAP documentation, I need to use MDDataSetBW object, by first creating the query object using CreateObject and then retrieving the results using GetAxisInfo and GetCellData.
Right now I am stuck at the very first step of just creating the query object. The documentation states that CreateObject has one import parameter CommandText and two export parameters DataSetID and Return. The problem is that according to SAP Documentation CommandText parameter is a table with a single column called LINE. So basically it's just an MDX query, with each line of the query being a value of the LINE column of each row of this table. The question is how do I pass it? Can anyone point me to a C++ example code that does something like this?
Here's my current prototype code:
#include "stdafx.h"
using namespace std;
RFC_HANDLE Logon()
{
RFC_CONNOPT_R3ONLY conn_options;
conn_options.hostname = SAP_LOGON::Hostname;
conn_options.sysnr = 0;
conn_options.gateway_host = nullptr;
conn_options.gateway_service = nullptr;
RFC_OPTIONS options;
options.mode = RFC_MODE_R3ONLY;
options.destination = SAP_LOGON::Destination;
options.client = SAP_LOGON::Client;
options.user = SAP_LOGON::User;
options.password = SAP_LOGON::Password;
options.language = SAP_LOGON::Language;
options.trace = 0;
options.connopt = &conn_options;
RFC_HANDLE hConn = RfcOpen(&options);
if (hConn == RFC_HANDLE_NULL)
ErrorHandler(_T("RfcOpen"));
return hConn;
}
void MakeStringParam(RFC_PARAMETER& param, rfc_char_t* name, rfc_char_t* buf, unsigned long size)
{
param.name = name;
param.nlen = (unsigned int)wcslen(name);
param.type = TYPC;
param.leng = size;
param.addr = &buf;
}
RFC_HANDLE WIN_DLL_EXPORT_FLAGS CreateQuery(RFC_HANDLE hConn, rfc_char_t* query)
{
rfc_char_t datasetID[256];
rfc_char_t ret[256];
RFC_PARAMETER exporting[3];
MakeStringParam(exporting[0], _T("DataSetID"), datasetID, 256);
MakeStringParam(exporting[1], _T("Return"), ret, 256);
exporting[2].name = nullptr;
// TODO: is it needed?
RFC_PARAMETER importing[2];
MakeStringParam(importing[0], _T("CommandText"), ret, 256);
importing[1].name = nullptr;
// TODO: put query into the table parameter
RFC_TABLE tables[2];
tables[0].name = _T("CommandText");
tables[1].name = nullptr;
rfc_char_t* ex = nullptr;
RFC_RC rc = RfcCallReceive(hConn, _T("BAPI_MDDATASETBW_CREATE_OBJECT"), exporting, importing, tables, &ex);
if (rc == RFC_OK)
{
// TODO: retrieve query handle here
RFC_HANDLE result = RFC_HANDLE_NULL;
return result;
}
return RFC_HANDLE_NULL;
}
int _tmain(int argc, _TCHAR* argv[])
{
RfcInit();
RFC_HANDLE hConn = Logon();
rfc_char_t* query = _T("\
SELECT\
{[Measures].[DA70CEZJ18267Q9RS4XFK7J32]} ON COLUMNS,\
{[0APO_LOCNO].[LEVEL01].AllMembers} ON ROWS\
FROM [0APO_C01/IDES_APO_04]");
RFC_HANDLE hQuery = CreateQuery(hConn, query);
// TODO: retrieve query results using
// - MDDataSetBW.GetAxisData
// - MDDataSetBW.GetAxisInfo
// - MDDataSetBW.GetCellData
RfcClose(hConn);
return 0;
}
How can I get the value of a primitive literal using libclang?
For example, if I have a CXCursor of cursor kind CXCursor_IntegerLiteral, how can I extract the literal value.
UPDATE:
I've run into so many problems using libclang. I highly recommend avoiding it entirely and instead use the C++ interface clang provides. The C++ interface is highly useable and very well documented: http://clang.llvm.org/doxygen/annotated.html
The only purpose I see of libclang now is to generate the ASTUnit object for you as with the following code (it's not exactly easy otherwise):
ASTUnit * astUnit;
{
index = clang_createIndex(0, 0);
tu = clang_parseTranslationUnit(
index, 0,
clangArgs, nClangArgs,
0, 0, CXTranslationUnit_None
);
astUnit = static_cast<ASTUnit *>(tu->TUData);
}
Now you might say that libclang is stable and the C++ interface isn't. That hardly matters, as the time you spend figuring out the AST with libclang and creating kludges with it wastes so much of your time anyway. I'd just as soon spend a few hours fixing up code that does not compile after a version upgrade (if even needed).
Instead of reparsing the original, you already have all the information you need inside the translation unit :
if (kind == CXCursor_IntegerLiteral)
{
CXSourceRange range = clang_getCursorExtent(cursor);
CXToken *tokens = 0;
unsigned int nTokens = 0;
clang_tokenize(tu, range, &tokens, &nTokens);
for (unsigned int i = 0; i < nTokens; i++)
{
CXString spelling = clang_getTokenSpelling(tu, tokens[i]);
printf("token = %s\n", clang_getCString(spelling));
clang_disposeString(spelling);
}
clang_disposeTokens(tu, tokens, nTokens);
}
You will see that the first token is the integer itself, the next one is not relevant (eg. it's ; for int i = 42;.
If you have access to a CXCursor, you can make use of the clang_Cursor_Evaluate function, for example:
CXChildVisitResult var_decl_visitor(
CXCursor cursor, CXCursor parent, CXClientData data) {
auto kind = clang_getCursorKind(cursor);
switch (kind) {
case CXCursor_IntegerLiteral: {
auto res = clang_Cursor_Evaluate(cursor);
auto value = clang_EvalResult_getAsInt(res);
clang_EvalResult_dispose(res);
std::cout << "IntegerLiteral " << value << std::endl;
break;
}
default:
break;
}
return CXChildVisit_Recurse;
}
Outputs:
IntegerLiteral 42
I found a way to do this by referring to the original files:
std::string getCursorText (CXCursor cur) {
CXSourceRange range = clang_getCursorExtent(cur);
CXSourceLocation begin = clang_getRangeStart(range);
CXSourceLocation end = clang_getRangeEnd(range);
CXFile cxFile;
unsigned int beginOff;
unsigned int endOff;
clang_getExpansionLocation(begin, &cxFile, 0, 0, &beginOff);
clang_getExpansionLocation(end, 0, 0, 0, &endOff);
ClangString filename = clang_getFileName(cxFile);
unsigned int textSize = endOff - beginOff;
FILE * file = fopen(filename.c_str(), "r");
if (file == 0) {
exit(ExitCode::CANT_OPEN_FILE);
}
fseek(file, beginOff, SEEK_SET);
char buff[4096];
char * pBuff = buff;
if (textSize + 1 > sizeof(buff)) {
pBuff = new char[textSize + 1];
}
pBuff[textSize] = '\0';
fread(pBuff, 1, textSize, file);
std::string res(pBuff);
if (pBuff != buff) {
delete [] pBuff;
}
fclose(file);
return res;
}
You can actually use a combination of libclang and the C++ interface.
The libclang CXCursor type contains a data field which contains references to the underlying AST nodes.
I was able to successfully access the IntegerLiteral value by casting data[1] to the IntegerLiteral type.
I'm implementing this in Nim so I will provide Nim code, but you can likely do the same in C++.
let literal = cast[clang.IntegerLiteral](cursor.data[1])
echo literal.getValue().getLimitedValue()
The IntegerLiteral type is wrapped like so:
type
APIntObj* {.importcpp: "llvm::APInt", header: "llvm/ADT/APInt.h".} = object
# https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/APInt.h
APInt* = ptr APIntObj
IntegerLiteralObj* {.importcpp: "clang::IntegerLiteral", header: "clang/AST/Expr.h".} = object
IntegerLiteral* = ptr IntegerLiteralObj
proc getValue*(i: IntegerLiteral): APIntObj {.importcpp: "#.getValue()".}
# This is implemented by the superclass: https://clang.llvm.org/doxygen/classclang_1_1APIntStorage.html
proc getLimitedValue*(a: APInt | APIntObj): culonglong {.importcpp: "#.getLimitedValue()".}
Hope this helps someone :)
Well I am attempting to make my way through developing an Excel Add-in. I am trying small functions with the sample code in Excel 2007 SDK as as a guide. I am having difficulty with attempting to display a double type data in Excel. Assuming the UDF is called DisplayDouble() when the sample code is executed and a call is placed with an argument of real type data such as DisplayDouble(12.3) the sample code works yet if I attempt to use an argument that references a real type data from cell such as DisplayDouble(A1) where cell A1 in the Excel worksheet has the value 12.3 the sample code does not work
You can see the sample code below this paragraph. Any hints will help me move along the learning ladder
_declspec(dllexport) LPXLOPER12 WINAPI DisplayDouble (LPXLOPER12 n)
{
static XLOPER12 xResult;
XLOPER12 xlt;
int error = -1;
double d;
switch (n->xltype)
{
case xltypeNum:
d = (double)n->val.num;
if (max < 0)
error = xlerrValue;
xResult.xltype = xltypeNum;
xResult.val.num = d;
break;
case xltypeSRef:
error = Excel12f(xlCoerce, &xlt, 2, n, TempNum12(xltypeNum));
if (!error)
{
error = -1;
d = xlt.val.w;
xResult.xltype = xltypeNum;
xResult.val.num = d;
}
Excel12f(xlFree, 0, 1, &xlt);
break;
default:
error = xlerrValue;
break;
}
if ( error != - 1 )
{
xResult.xltype = xltypeErr;
xResult.val.err = error;
}
//Word of caution - returning static XLOPERs/XLOPER12s is not thread safe
//for UDFs declared as thread safe, use alternate memory allocation mechanisms
return(LPXLOPER12) &xResult;
}
looks like you coerced the value to xltypeNum but are then taking the integer value, with d = xlt.val.w rather than d = xlt.val.num