How to return array from XLL function - c++

I am new in writing XLL, Anyone knows how to return a 6x1 array to Excel ?
The following is my function (some codes came from other post):
__declspec(dllexport) LPXLOPER12 WINAPI GetArr(char* arg1, char* arg2)
{
vector<double> arr = functionReturnVector;
XLOPER12 list;
list.xltype = xltypeMulti | xlbitDLLFree;
list.val.array.lparray = new XLOPER12[6];
list.val.array.rows = 6;
list.val.array.columns = 1;
for(int i = 0; i < 6; ++i) {
list.val.array.lparray[i] = arr[i]; // error: IntelliSense: no operator "=" matches these operands
}
return &list;
}
[2013-02-23]
Currently I read the codes from XLL RETURN ARRAY and review my code, it can compile but returns 0 ...
__declspec(dllexport) LPXLOPER12 WINAPI GetArr(void)
{
XLOPER xlArray, xlValues[2];
xlValues[0].xltype = xltypeNum;
xlValues[1].xltype = xltypeNum;
xlValues[0].val.num = 11;
xlValues[1].val.num = 17;
xlArray.xltype = xltypeMulti|xlbitDLLFree;
xlArray.val.array.rows = 1;
xlArray.val.array.columns = 2;
xlArray.val.array.lparray = &xlValues;
return &xlArray;
}

I can print an 1X2 array in Excel worksheet now, the following is my code.
**use Func signature type U
1.select one row and two columns
2.Type command =GetArray() in first cell
3.Ctrl + shift + enter
__declspec(dllexport) LPXLOPER12 WINAPI GetArray(void)
{
static XLOPER12 xlArray;
XLOPER12 xlValues[2];
xlValues[0].xltype = xltypeNum;
xlValues[1].xltype = xltypeNum;
xlValues[0].val.num = 123;
xlValues[1].val.num = 456;
xlArray.xltype = xltypeMulti|xlbitDLLFree;
xlArray.val.array.rows = 1;
xlArray.val.array.columns = 2;
xlArray.val.array.lparray = &xlValues;
return (LPXLOPER12)&xlArray;
}

Maybe http://xll.codplex.com can help you solve your problem, but as other people that are trying to help you, your code seems pretty far from shore.
On ne découvre pas de terre nouvelle sans consentir à perdre de vue, d'abord et longtemps, tout rivage.
Just kidding. Maybe that will work for you.

Related

Building a css grid with javascript: creating elements, storing them in arrays and append them to other elements

I recently build an masonry gallery with html and css. I used the display: grid; property to make it look like so. Now I am trying to create randomized layouts. Therefor I want to create elements with classes. I want to append / elements to the elements, store those elements inside an array and later append them inside my "masonry" . I put in different console.logs to see whats happening, but I get some either weird or undefined returns. Javascript can be as tricky as it can be fun for beginners, so I hope you guys can help me out.
Thank you all. :)
//arrays and variables
const figures = [];
let newFigures = "";
const divs = [];
let newDivs = "";
function makeCells(){
for(let i = 0; i < 33; i++){
newFigure = document.createElement("figure");
figures[i] = newFigure.classList.add("cell", "cell--" + i);
newDiv = document.createElement("div");
divs[i] = newDiv.setAttribute("id", i);
console.log("log1: " + newFigure.classList);
console.log("log2: " + figures[i]);
}
console.log("log3: " + divs);
console.log("log4: " + figures);
console.log("log5: " + divs);
for(let i=0; i<3; i++){
figures[i] = newFigure.appendChild(newDiv);
}
console.log("figures = " + figures);
console.log("divs = " + divs);
let z = {};
for(let i=0; i<3; i++){
z = figures[i];
document.getElementById("masonry").appendChild(z);
}
console.log(document.getElementById("masonry"));
}
Here is a picture of the corresponding console.logs.
Console Logs
This works as intended:
const figures = [];
let newFigure = "";
const divs = [];
let newDiv = "";
function makeCells(){
for(let i = 0; i < 33; i++){
newFigure = document.createElement("figure");
newDiv = document.createElement("div");
newFigure.appendChild(newDiv);
document.getElementById("masonry").appendChild(newFigure);
figures[i] = newFigure.classList.add("cell", "cell--" + i);
}
console.log(document.getElementById("masonry"));
}
Sorry to bother you guys.
I don't like this line of code, mainly because the add() method does not have a return value.
figures[i] = newFigure.classList.add("cell", "cell--" + i);
I would split it into two statements.
newFigure.classList.add("cell", "cell--" + i);
figures.push(newFigure);

VARIANT export/import C++ DLL SAFEARRAY

I know that this topic is quite popular. However, I'd like to solve a simple problem... My target is to create a DLL in C++ able to import and export data matrices from VB (Excel or other programs). I read in some blogs that a common way to do that is to use the SAFEARRAYs.
So, I created the following C++ code:
VARIANT _stdcall ReadArrayVBA_v1(VARIANT *Input0) {
double dm = 0, rm = 0;
//OUTPUT DATA DEFINITION
VARIANT v;
SAFEARRAYBOUND Dim[1];
Dim[0].lLbound = 0; Dim[0].cElements = 4;
v.vt = VT_R8;
v.parray = SafeArrayCreate(VT_R8, 1, Dim);
//==============================================
SAFEARRAY* pSafeArrayInput0 = NULL; //Define a pointer SAFEARRAY Type
pSafeArrayInput0 = *V_ARRAYREF(Input0);
long lLBound = -1, lUBound = 1; //Preset dimension
SafeArrayGetLBound(pSafeArrayInput0, 1, &lLBound);
SafeArrayGetUBound(pSafeArrayInput0, 1, &lUBound);
long CntElements = lUBound - lLBound + 1;
long Index[1];
for (int i=0; i<CntElements; i++){
Index[0] = i;
SafeArrayGetElement(pSafeArrayInput0, Index, &dm);
rm = dm + 1;
SafeArrayPutElement(v.parray, Index, &rm);
}
return v;
}
It compiles and I call from VBA Excel in the following manner:
Private Declare Function ReadArrayVBA_v1 Lib "[PATH]\VARIANTtest.dll" (ByRef Input0 As Variant) As Variant
Sub VBACall()
Dim InputR0(1 To 4) As Variant
Dim vResult1 As Variant
InputR0(1) = 2
InputR0(2) = 20
InputR0(3) = 200
InputR0(4) = 240
vResult1 = ReadArrayVBA_v1(InputR0)
End Sub
The function gives me back values such as 1.2E-305 and similar. Why?

How to read data in vtkDataArray?

I am ver new to VTK.
This is part of my code:
vtkDataSetReader *rdr = vtkDataSetReader::New();
rdr->SetFileName("proj7b.vtk");
rdr->SetScalarsName("hardyglobal");
rdr->Update();
int dims[3];
vtkRectilinearGrid *rgrid = (vtkRectilinearGrid *) rdr->GetOutput();
rgrid->GetDimensions(dims);
vtkDataArray *dataArray;
dataArray = vtkDoubleArray::New();
dataArray = rgrid->GetPointData()->GetScalars()->GetVoidPointer(0);
for(i=0;i<10;i++)
{
cout<<"here----------"<<endl;
cout<<" "<<dataArray[i]<<" ";
}
I want to read the data into my vtkDataArray. But this code cannot be compile:
proj7b.cxx:525:15: error:
assigning to 'vtkDataArray *' from incompatible type 'void *'
dataArray = rgrid->GetPointData()->GetScalars()->GetVoidPointer(0);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Is there anyone knows how to read data into vtkDataArray?
Vtk provides the method for it, you don't need to use the "low level" method:
rgrid->GetPointData()->GetArray(0)
or
rgrid->GetPointData()->GetArray("arrayname")
It works the same way for FieldData and CellData ( http://www.vtk.org/doc/release/6.2/html/classvtkFieldData.html)
What you get is a vtkArray, not a simple c++ array, so you will have to read it like:
cout<<" "<<dataArray->GetValue(i) <<" ";
There are a lot of examples in the wiki http://www.vtk.org/Wiki/VTK/Examples/Cxx
please see this page: https://cloud.tencent.com/developer/ask/sof/148655
void doSomething(vtkSmartPointer<vtkDataArray> dataArray)
{
vtkIdType numTuples = dataArray->GetNumberOfTuples();
for (vtkIdType tupleIdx = 0; tupleIdx < numTuples; ++tupleIdx)
{
double* tuple = dataArray->GetTuple(tupleIdx);
for (int j = 0; j < /*¿¿¿???*/; ++j)
{
double var = tuple[j];
// Do something with var
// Carefull don't go out of bounds
}
}
}

Trouble with byte array marshaling in ObjC/C++ to C# in IOS

** This is still unsolved **
I'm trying to call an ObjC/C++ function code from C#. I've done my best to follow different example code, the latest being mostly from:
http://msdn.microsoft.com/en-us/library/ms146631(v=VS.80).aspx
This is for an iPhone/MonoTouch environment, so I'm not sure I've done everything I should. The bytes appear to be ok in the ObjC/C++ function, but the byte array I get back into C# ends up containing 0 0 0 0 0 0 etc.
** Update **
Corrected for loop initializer, and now its giving a EXC_BAD_ACCESS signal on the *returnbytes[i] = bytes[i]; line.
C# code:
[DllImport ("__Internal")]
private static extern int _getjpeg(string url,ref IntPtr thebytes);
void somefunction(string image_id) {
int maxsize = 50000;
byte[] thebytes = new byte[maxsize];
IntPtr byteptr = Marshal.AllocHGlobal(maxsize);
int imagesize = _getjpeg(image_id,ref byteptr);
Debug.Log("Getting _picturesize()... "+ image_id);
int picsize = _picturesize();
Marshal.Copy(byteptr,thebytes,0,picsize);
var texture = new Texture2D(1,1);
string bytedebug = "";
for (int i=5000 ; i < 5020 ; i++)
bytedebug+=thebytes[i] + " ";
Debug.Log("Bytes length is "+imagesize);
Debug.Log("Bytes content is "+bytedebug);
}
C++/ObjC code:
int _getjpeg(const char* url,unsigned char** returnbytes) {
ALAsset* asset = [_pictures objectForKey:[NSString stringWithUTF8String:url]];
if(asset != NULL)
NSLog(#"_getjpeg() found URL: %#",[NSString stringWithUTF8String: url]);
else {
NSLog(#"_getjpeg() could not find URL: %#",[NSString stringWithUTF8String: url]);
return NULL;
}
UIImage *image = [UIImage imageWithCGImage: [asset thumbnail]];
NSData* pictureData = UIImageJPEGRepresentation (image, 1.0);
picturesize = (int)[pictureData length];
unsigned char* bytes = (unsigned char*)[pictureData bytes];
// This test does not give EXC_BAD_ACCESS
*returnbytes[5] = (unsigned int)3;
// updated below initializer in below for loop according to Eikos suggestion
for(int i=0 ; i < picturesize ; i++) {
// below lines gives EXC_BAD_ACCESS
*returnbytes[i] = bytes[i];
}
NSString* debugstr = [NSString string];
for(int i=5000; i < 5020 ; i++) {
unsigned char byteint = bytes[i];
debugstr = [debugstr stringByAppendingString:[NSString stringWithFormat:#"%i ",byteint]];
}
NSLog(#"bytes %s",[debugstr UTF8String]);
return picturesize;
}
Thanks
Keep in mind that the JPGRepresentation is probably not exactly the same as you put into it, so the length may differ.
In
for(int i;i < picturesize;i++) {
// *** Not sure I'm doing this correctly ***
*returnbytes[i] = bytes[i];
}
you forget to initialize i, so it might start with a random value which is bigger than picturesize, so the loop won't run at all.
You want unsigned char*, not **. You are passing a pointer in that is already allocated. A ** is for when you are passing in a pointer to variable that is itself a pointer to data: i.e. when the callee will allocate the memory and the caller wants to know about it.
Just pass in unsigned char* and then use
returnbytes[i] = bytes[i];
Alternatively, allocate in the calee and use an out, not a ref.

What am I doing wrong? (multithreading)

Here s what I'm doing in a nutshell.
In my class's cpp file I have:
std::vector<std::vector<GLdouble>> ThreadPts[4];
The thread proc looks like this:
unsigned __stdcall BezierThreadProc(void *arg)
{
SHAPETHREADDATA *data = (SHAPETHREADDATA *) arg;
OGLSHAPE *obj = reinterpret_cast<OGLSHAPE*>(data->objectptr);
for(unsigned int i = data->start; i < data->end - 1; ++i)
{
obj->SetCubicBezier(
obj->Contour[data->contournum].UserPoints[i],
obj->Contour[data->contournum].UserPoints[i + 1],
data->whichVector);
}
_endthreadex( 0 );
return 0;
}
SetCubicBezier looks like this:
void OGLSHAPE::SetCubicBezier(USERFPOINT &a,USERFPOINT &b, int &currentvector )
{
std::vector<GLdouble> temp;
if(a.RightHandle.x == a.UserPoint.x && a.RightHandle.y == a.UserPoint.y
&& b.LeftHandle.x == b.UserPoint.x && b.LeftHandle.y == b.UserPoint.y )
{
temp.clear();
temp.push_back((GLdouble)a.UserPoint.x);
temp.push_back((GLdouble)a.UserPoint.y);
ThreadPts[currentvector].push_back(temp);
temp.clear();
temp.push_back((GLdouble)b.UserPoint.x);
temp.push_back((GLdouble)b.UserPoint.y);
ThreadPts[currentvector].push_back(temp);
}
}
The code that calls the threads looks like this:
for(int i = 0; i < Contour.size(); ++i)
{
Contour[i].DrawingPoints.clear();
if(Contour[i].UserPoints.size() < 2)
{
break;
}
HANDLE hThread[4];
SHAPETHREADDATA dat;
dat.objectptr = (void*)this;
dat.start = 0;
dat.end = floor((Contour[i].UserPoints.size() - 1) * 0.25);
dat.whichVector = 0;
dat.contournum = i;
hThread[0] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0);
dat.start = dat.end;
dat.end = floor((Contour[i].UserPoints.size() - 1) * 0.5);
dat.whichVector = 1;
hThread[1] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0);
dat.start = dat.end;
dat.end = floor((Contour[i].UserPoints.size() - 1) * 0.75);
dat.whichVector = 2;
hThread[2] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0);
dat.start = dat.end;
dat.end = Contour[i].UserPoints.size();
dat.whichVector = 3;
hThread[3] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0);
WaitForMultipleObjects(4,hThread,true,INFINITE);
}
Is there something wrong with this?
I'd expect it to fill ThreadPts[4]; ... There should never be any conflicts the way I have it set up. I usually get error writing at... on the last thread where dat->whichvector = 3. If I remove:
dat.start = dat.end;
dat.end = Contour[i].UserPoints.size();
dat.whichVector = 3;
hThread[3] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0);
Then it does not seem to crash, what could be wrong?
Thanks
The problem is that you're passing the same dat structure to each thread as the argument to the threadproc.
For example, When you start thread 1, there's no guarantee that it will have read the information in the dat structure before your main thread starts loading that same dat structure with the information for thread 2 (and so on). In fact, you're constantly directly using that dat structure throughout the thread's loop, so the thread won't be finished with the structure passed to it until the thread is basically done with all its work.
Also note that currentvector in SetCubicBezier() is a reference to data->whichVector, which is referring to the exact same location in a threads. So SetCubicBezier() will be performing push_back() calls on the same object in separate threads because of this.
There's a very simple fix: you should use four separate SHAPETHREADDATA instances - one to initialize each thread.