Migration of JCoFunction in sapjco 3.x - jco

I'm migrating from JCO2.x to 3.x. I have rewritten almost the whole code, but with this I cannot move.
Original 2.x code:
JCO.ParameterList input = new JCO.ParameterList();
input.addInfo("APP_AREA", JCO.TYPE_STRING, 0, 0, 0, JCO.IMPORT_PARAMETER, null);
input.addInfo("XML", JCO.TYPE_STRING, 0, 0, 0, JCO.IMPORT_PARAMETER, null);
JCO.Function function = new JCO.Function(
BAPI_NAMESPACE + "ZZZ",
input, // input
new JCO.ParameterList(), // output
new JCO.ParameterList() // tables
);
My proposed code:
JCoParameterList input = new JCoParameterList();
input.addInfo("APP_AREA", JCO.TYPE_STRING, 0, 0, 0, JCO.IMPORT_PARAMETER, null);
input.addInfo("XML", JCO.TYPE_STRING, 0, 0, 0, JCO.IMPORT_PARAMETER, null);
JCoFunction function = new JCoFunction(
BAPI_NAMESPACE + "ZZZ",
input, // input
new JCoParameterList(), // output
new JCoParameterList() // tables
);
Thing is that JCoFunction cannot be instantiated in this form in 3.x. Should I create function template? Thank you for any hints.

.... a little late response...
You have to get the JcoFunction from your JcoDestination.
e.g.
JCoDestination destination = JCoDestinationManager
.getDestination(destinationName);
JCoRepository repository = destination.getRepository();
JCoFunctionTemplate template = repository.getFunctionTemplate(functionName);
JCoFunction function = template.getFunction();
JCoParameterList input = function_.getImportParameterList();
//set data on input
//execute the function
function.execute(destination);
//access the output
JCoParameterList output = function_.getExportParameterList();
JCoParameterList table = function_.getTableParameterList();

Related

IXAudio2Engine::CreateSourceVoice fails

I receive the Error XAUDIO2_E_INVALID_CALL when I try to call IXAudio2Engine::CreateSourceVoice. My code for creating a source voice is as follows:
auto sample_rate = quality_to_sample_rate(settings.quality, sound_category::effect);
WAVEFORMATEX wave_format{ // 8000Hz 16 bit mono WAV
.wFormatTag = WAVE_FORMAT_PCM,
.nChannels = 1,
.nSamplesPerSec = sample_rate,
.nAvgBytesPerSec = sample_rate* 2,
.wBitsPerSample = 16,
.cbSize = 0,
};
XAUDIO2_SEND_DESCRIPTOR send_descriptor{.Flags = 0, .pOutputVoice = master_voice};
XAUDIO2_VOICE_SENDS sends{.SendCount = 1, .pSends = &send_descriptor};
res = sound_engine->CreateSourceVoice(&v, &wave_format, 0, 2.0f, nullptr, &sends);
if(FAILED(res)) {
log_error("Could not create effect source voice with", sample_rate, "Hz");
throw std::runtime_error("Could not create effect source voice");
}
log_debug("Created effect source voice with ", sample_rate, "Hz at ", (void*)v);
master_voice is not nullptr and is of type IXAudio2MasteringVoice* (i.e. CreateMasteringVoice returned S_OK!)
What am I missing?
Edit:
According to XAudio2 and *.wav loading, HRESULT 0x88960001 ,
it is possible to set pSendList to NULL which would result in using the MasteringVoice. but that does not help either.
Reading the docs helps:
nBlockAlign and nAvgBytesPerSecond need to be set correctly.
nBlockAlign needs to be (nChannels * (nBitsPerSample/8)) / 8 and
nAvgBytesPerSecond is nBlockAlign * nSamplesPerSecond

failed when calling luaT_pushudata for the second time in a loop

I am using lua's c api and had some trouble.
When I am doing some loops, luaT_pushudata always fails when I called it for the second time and said that
'no source available for lua_newuserdata() at 0x7ffff7ba85b3'
(when debugging in eclipse)
And when directly running the excusable, it just said '
segmentation fault (core dumped)
here is part of my codes (they are within a loop):
// establish the new tuple
tupleA temptupleA;
// cannot delete the buffer_char, the buffer char must be deallocate manually when erase the vector
unsigned char * buffer_char = new unsigned char[rect.width*rect.height*3];
glReadPixels(0, 0, rect.width, rect.height, GL_RGB, GL_UNSIGNED_BYTE, buffer_char);
temptupleA.pic = buffer_char;
temptupleA.action = new double[3];
temptupleA.reward = new double[1];
totalBuffer.push_back(temptupleA);
// set action
// get the Action
double * buffer = charA2fA(totalBuffer[totalStep].pic, raw_width*raw_height*3);
//std::cout<<buffer[raw_width*raw_height*3-1]<<std::endl;// check
THDoubleStorage *mystorage0 = THDoubleStorage_newWithData(&buffer[0], raw_width*raw_height*3);
THDoubleTensor* mytensor0 = THDoubleTensor_newWithStorage4d(
mystorage0, 0,
1, raw_width*raw_height*3,
3, raw_width*raw_height,
raw_width, raw_height,
raw_height, raw_width);
lua_getglobal(L, "returnAction");
std::cout<<totalStep; //check
luaT_pushudata(L, (void *)mytensor0, "torch.DoubleTensor"); // there is something wrong
std::cout<<" pass the luaT_pushudata"<<std::endl;
if(lua_pcall(L,1,3,0)) lua_error(L);
d->ctrl[0] = lua_tonumber(L,-3);
d->ctrl[1] = lua_tonumber(L,-2);
d->ctrl[2] = lua_tonumber(L,-1);
totalBuffer[totalStep].action[0]=d->ctrl[0];
totalBuffer[totalStep].action[1]=d->ctrl[1];
totalBuffer[totalStep].action[2]=d->ctrl[2];
lua_remove(L, -1);
lua_remove(L, -2);
lua_remove(L, -3);
THDoubleTensor_free(mytensor0);
delete [] buffer;
So what may be the cause of the problem??
I have found the problem: instead of writing lua_remove(L, -1), lua_remove(L, -2), lua_remove(L, -3) I should simply write lua_pop(L, 3) or write lua_remove(L, -1) for three times
luaT_pushudata steals a references, so you might access freed memory. Check with valgrind.

Clearing the stm32f4-discovery flash programatically

I'm having a problem clearing the stm32f429 discovery board flash after creating a window using stemwin library. If I use the code below, flash will be cleared correctly:
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR_22;
EraseInitStruct.NbSectors = 1;
HAL_FLASH_Unlock();
uint32_t sectorError = 0;
if(HAL_FLASHEx_Erase(&EraseInitStruct,&sectorError)!=HAL_OK)
{
return HAL_FLASH_GetError();
}
HAL_FLASH_Lock();
CreateWindow();
But if I bring the CreateWindow() function to top of the code, flash will not be cleared. Here is CreateWindow() function:
WM_HWIN CreateWindow(void)
{
hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbDialog, WM_HBKWIN, 0, 0);
hMultiPage = MULTIPAGE_CreateEx(0, -20, 320, 260, WM_GetClientWindow(hWin), WM_CF_SHOW, 0, 0);
MULTIPAGE_SetSkin(hMultiPage,MULTIPAGE_SKIN_FLEX);
hPage1 = GUI_CreateDialogBox(_aDialogCreate2, GUI_COUNTOF(_aDialogCreate2), _cbDialogPage1, WM_UNATTACHED, 0, 0);
MULTIPAGE_AddPage(hMultiPage, hPage1, "Settings");
hPage2 = GUI_CreateDialogBox(_aDialogCreate3, GUI_COUNTOF(_aDialogCreate3), _cbDialogPage2, WM_UNATTACHED, 0, 0);
MULTIPAGE_AddPage(hMultiPage, hPage2, "Run");
MULTIPAGE_SelectPage(hMultiPage,0);
return hWin;
}
These 2 things has nothing to do between.
There could be a problem, however, that you want to delete sector where data are located (maybe images or similar) for your GUI.
Technically, there is no other option here.
Also, check which value "SectorError" variables has after function completes?

how to change Text to Speech voice and how to insert characters into char array

I need to change the voice of the Text To Speech engine. When a menu is selected (ID_SPEAK_PLAY), I get the text of an edit box and simply read it.
My situation can be solved in two ways :
insert the XML code at the begining of ptrData without using strncat or other functions that involve creating other wchar_t* buffers (memory issues ). StringCchPrintf is not working.
change the voice in some other way that i don't know.
Here is my code :
case ID_SPEAK_PLAY:
text_size = SendMessage(h_edit, WM_GETTEXTLENGTH, 0, 0);
text_size += 100;
ptrData = new wchar_t[text_size];
SendMessage(h_edit, WM_GETTEXT, text_size, (LPARAM)ptrData);
StringCchPrintf(ptrData, text_size, L"<voice required = \"Gender=Female;Age=Teen\"> %s", ptrData);
pVoice->Speak(ptrData, SPF_ASYNC | SPF_IS_XML, NULL);
delete [] ptrData;
break;
StringCchPrintf is not working.
That is because you ignored the warning in the documentation:
Behavior is undefined if the strings pointed to by pszDest, pszFormat, or any argument strings overlap.
You are specifying ptrData as both pszDest and an argument string, so your code has undefined behavior. You must use separate buffers when using StringCchPrintf():
case ID_SPEAK_PLAY:
text_size = SendMessage(h_edit, WM_GETTEXTLENGTHW, 0, 0) + 1;
ptrData = new wchar_t[text_size];
SendMessage(h_edit, WM_GETTEXTW, text_size, (LPARAM)ptrData);
speak_size = text_size + 100;
speakData = new wchar_t[speak_size];
StringCchPrintf(speakData, speak_size, L"<voice required = \"Gender=Female;Age=Teen\"> %s", ptrData);
pVoice->Speak(speakData, SPF_ASYNC | SPF_IS_XML, NULL);
delete [] speakData;
delete [] ptrData;
break;
Alternatively, just skip StringCchPrintf() and let WM_GETTEXT populate your single buffer directly:
case ID_SPEAK_PLAY:
{
const wchar_t *xml = L"<voice required = \"Gender=Female;Age=Teen\"> ";
const int xml_size = lstrlenW(xml);
text_size = SendMessage(h_edit, WM_GETTEXTLENGTHW, 0, 0);
ptrData = new wchar_t[text_size + xml_size + 1];
lstrcpyW(ptrData, xml);
SendMessage(h_edit, WM_GETTEXTW, text_size+1, (LPARAM)(ptrData+xml_size));
pVoice->Speak(ptrData, SPF_ASYNC | SPF_IS_XML, NULL);
delete [] ptrData;
break;
}
change the voice in some other way that i don't know.
Instead of inserting XML in front of your text, you can call the ISpVoice::SetVoice() method before calling ISpVoice::Speak(). Use SpEnumTokens() to know which voices are installed, or use SpFindBestToken() to search for a voice that matches the criteria you need.

Call OCIStmtExecute() with ref cursor and OCI_ATTR_PREFETCH_ROWS?

I can call a stored procedure via OCI with a ref cursor, then iterate over the results using a call to OCIStmtFetch2() each time. My question is how can I loop over a set of rows so I don't have to call OCIStmtFetch2() each time? Presume the answer will be something with OCI_ATTR_PREFETCH_ROWS but I cant seem to get this working as access voilations are being thrown everytime I call OCIStmtExecute.
http://www.sqlines.com/oracle/oci/array_fetch works for select statements but I want to use it for a cursor which crashes on my implementation. Sorry for code length but here is the full function:
OCIError* pOciError;
OCIStmt* pOciStatement;
char* sqlCharArray = "BEGIN fxt.fxt_get_risk_trns('SOD', '29-SEP-2014', :refCursor ); END;";
OCIEnv* g_pOciEnvironment = NULL;
OCIServer* g_pOciServer = NULL;
OCISession* g_pOciSession = NULL;
OCISvcCtx* g_pOciServiceContext = NULL;
sb2* pIndicator=0;
OCIDefine* pOciDefine2;
OCIBind* pBind;
OCIStmt* cursor;
int answer = OCIEnvCreate((OCIEnv **)&g_pOciEnvironment, (ub4)OCI_THREADED ,
(void *)0, (void * (*)(void *, size_t))0,
(void * (*)(void *, void *, size_t))0,
(void (*)(void *, void *))0,
(size_t)0, (void **)0);
<snip boilerplate code>
const int prefetchSize(PREFETCH_ROWS_SIZE);
answer = OCIHandleAlloc(g_pOciEnvironment , (void **)(&pOciStatement), OCI_HTYPE_STMT, 0, NULL);
answer = OCIAttrSet(pOciStatement, OCI_HTYPE_STMT, (void*)&prefetchSize, sizeof(int), OCI_ATTR_PREFETCH_ROWS, pOciError);
answer = OCIStmtPrepare(pOciStatement, pOciError, (unsigned char *)sqlCharArray, strlen(sqlCharArray),OCI_NTV_SYNTAX, OCI_DEFAULT);
answer = OCIHandleAlloc(g_pOciEnvironment, (void **)(&cursor), OCI_HTYPE_STMT, 0, NULL);
answer = OCIBindByPos(pOciStatement, &pBind, pOciError, 1, &cursor, 0, SQLT_RSET, pIndicator, 0, NULL, 0, 0, OCI_DEFAULT);
// Fetched data indicators, lengths and codes
char dealSTSCode[PREFETCH_ROWS_SIZE][4000];
sb2 dealSTSCode_ind[PREFETCH_ROWS_SIZE];
ub2 dealSTSCode_len[PREFETCH_ROWS_SIZE], dealSTSCode_code[PREFETCH_ROWS_SIZE];
answer = OCIAttrSet(cursor, OCI_HTYPE_STMT, (void*)&prefetchSize, sizeof(int), OCI_ATTR_PREFETCH_ROWS, pOciError);
// Unhandled exception thrown here, Access violation reading location xxx
answer = OCIStmtExecute(g_pOciServiceContext, pOciStatement, pOciError, PREFETCH_ROWS_SIZE, 0, NULL, NULL, OCI_DEFAULT);
answer = OCIDefineByPos(cursor,&pOciDefine2, pOciError,6, (void*)&dealSTSCode, 4000, SQLT_STR, dealSTSCode_ind, dealSTSCode_len, dealSTSCode_code,OCI_DEFAULT);
if (answer == 0)
{
int rowsFetched = 0;
do
{
if (!OCIStmtFetch2(cursor, pOciError, 100, OCI_FETCH_NEXT,0,OCI_DEFAULT))
{
OCIAttrGet(cursor, OCI_HTYPE_STMT, (void*)&rowsFetched, NULL, OCI_ATTR_ROWS_FETCHED, pOciError);
for (int i = 0; i != rowsFetched; ++i)
{
// process row
}
}
}
while (rowsFetched > 0);
}
I have found a solution to this. Needed to try some more combinations of calls but eventually got there. I have corrected the original code to reflect the correct solution.
The Key thing is to define the prefetch rows attribute on the cursor itself, not the statement pointer.